Android - RenderScript - Падение производительности в SDK 21

Я разрабатываю проект, который требует сложных эффектов наложения типа Photoshop. Я использую кастом RenderScript сценарии, чтобы решить это.

Я проверял это на Samsung Galaxy S4 На устройстве работает Kitkat, и все работает отлично и очень быстро.

Затем я попытался протестировать его на Nexus 5 под управлением Lollipop, и я заметил внезапное падение производительности.

Я начал синхронизировать отдельные разделы в коде, чтобы увидеть, какие части замедляются, и придумал следующее:

Allocation.createFromBitmap
- Runtime on Kitkat - ~5-10 millisec
- Runtime on Lollipop - ~100-150 millisec

mRenderScript.destory()
- Runtime on Kitkat - ~1-3 millisec
- Runtime on Lollipop - ~60-100 millisec

Мне любопытно, почему происходит внезапное падение производительности при создании Allocation объекты и уничтожение RenderScript объекты на устройстве, которое должно быть сильнее, и на ОС, которая должна быть более продвинутой.

Могу ли я что-нибудь сделать для ОС API 21, чтобы эти методы работали быстрее?

Кто-нибудь вообще сталкивался с этой проблемой или может ее воспроизвести?

Я должен отметить, что фактическое выполнение скрипта (т.е. ScriptC.forEach метод) работает очень быстро на обоих устройствах / ОС. Также я пользуюсь родным RenderScript API, а не какие-либо библиотеки поддержки.

Любой вклад будет оценен.

Редактировать:

Я скопировал соответствующую строку из исходного кода Android-релиза Lollipop в Github of Allocation.java

static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
            return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
                                    USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
        }
        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
                                USAGE_GRAPHICS_TEXTURE);
    }

Обратите внимание, что когда целевой SDK выше 17, распределение создается по умолчанию с USAGE_SHARED флаг. Может ли быть, что эти дополнительные флаги вызывают проблему? Должен ли я использовать USAGE_GRAPHICS_TEXTURE флаг вместо?

Редактировать 2

Следуя совету Р. Джейсона Сэма, я запустил следующий скрипт, когда Nexus 5 был подключен к моему компьютеру:

adb shell setprop debug.rs.default-CPU-driver 1

После этого время выполнения указанных функций значительно быстрее (~30-40 миллисекунд и 20-50 миллисекунд соответственно). Все еще не так быстро, как устройства перед леденцом на палочке, но в пределах допустимого диапазона производительности.

Моя единственная проблема с этим решением - то, что, если я чего-то не понимаю, не может считаться решением, так как это потребовало бы от меня вызова этого скрипта на каждом проблемном устройстве перед запуском приложения на нем.

Что-нибудь, что я могу сделать в своем коде, который может симулировать этот вызов adb?

Окончательное редактирование

Итак, похоже, что проблема возникла из-за того, что я создавал новый объект RenderScript каждый раз, когда вызывал функцию, которая выполняла эффект наложения с использованием RenderScript.

Я провел некоторый рефакторинг кода, и теперь вместо создания нового объекта RenderScript при каждом вызове метода эффекта я снова использую один и тот же объект каждый раз. Первое создание объекта RenderScript по-прежнему занимает гораздо больше времени для создания на устройствах Lollipop, но теперь проблема устранена, поскольку я продолжаю повторно использовать один и тот же объект в течение нескольких вызовов метода.

Я добавлю это как ответ.

2 ответа

Решение

Кажется, проблема возникла из-за того, что я создавал новый RenderScript объект каждый раз, когда я вызывал функцию, которая выполняла эффект наложения, используя RenderScript,

Я сделал некоторый рефакторинг кода и теперь вместо создания нового RenderScript объект при каждом вызове метода эффекта, я использую один и тот же каждый раз. 1-е создание RenderScript Создание объекта по-прежнему занимает гораздо больше времени на устройствах Lollipop, но теперь проблема устранена, поскольку я продолжаю повторно использовать один и тот же объект в течение нескольких вызовов методов.

Я обязательно позвоню destory() на общем RenderScript если я уверен, что он мне больше не нужен, чтобы не было утечек памяти.

Согласно этому посту, кажется, что повторное использование является честной практикой RenderScript объекты, а не создание нового каждый раз, но я был бы рад услышать мнение других людей относительно их опыта в этом вопросе. Жаль, что в Интернете не так много документации по этой теме, но пока все работает хорошо на разных устройствах.

В Api 18 был добавлен тип распределения (USAGE_SHARED). Если вы заставляете Renderscript копировать резервную копию растрового изображения (вместо того, чтобы использовать ее на месте), это может объяснить разницу.

 Allocation tmpOut = Allocation.createFromBitmap(mRenderContext, result, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SHARED);
Другие вопросы по тегам