Renderscript ScriptC 编译阻塞主线程
Renderscript ScriptC compile blocking main thread
我正在开发一个使用自定义 RenderScript 脚本进行图像处理的应用程序。现在,因为我有很多这些脚本在使用中,所以我在应用程序首次启动时预加载它们。 "preload" 我的意思是我实例化每个脚本,以便它可以在设备上编译。下面是这个操作的代码片段。大约有60个脚本,但我认为这足以说明操作。
public class Load extends Thread {
public Load() {
super();
setPriority(Thread.MIN_PRIORITY);
}
@Override
public void run() {
new ScriptC_first(RenderScriptHelper.getInstance());
new ScriptC_second(RenderScriptHelper.getInstance());
new ScriptC_third(RenderScriptHelper.getInstance());
}
}
如您所见,我是在后台线程上执行此操作的。问题是脚本似乎在主线程上编译,不管这个。问题是他们正在阻止 UI。我用 AsyncTask 和 Service 试过这个,结果相同。我怀疑 RenderScript 在内部跳到主线程来编译它们。
现在,在 Android Nougat (7.0) 之前,预加载相同数量的脚本需要不到 10 秒,具体取决于设备速度。在 Nougat 上,这需要将近一分钟的时间,考虑到它会阻止 UI,这是一个大问题,尽管只是在第一次应用程序启动时。在随后的每次启动中,它都会在几秒钟内预加载(因为脚本已经编译)。
我需要预加载,因为按需实例化脚本不是一种选择,因为一旦用户开始使用应用程序,所有脚本都必须准备好并编译。
logcat的相关部分:
E/RenderScript: Unable to open shared library (/data/user/0/com.company.myapp/cache/librs.contrast_v001.so): undefined symbol: .rs.dtor
V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore.bc -mtriple armv7-none-linux-gnueabi -O 3 -load libbccQTI.so -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe'
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so'
此外,如果相关的话,我在第一次启动应用程序时使用 RenderScript.ContextType.PROFILE,在随后的每次启动时使用 RenderScript.ContextType.NORMAL。使用 RenderScript.ContextType.DEBUG 会导致脚本在每次应用程序启动时编译,所用时间与其他上下文相同,并且 logcat 输出略有不同:
V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore_debug.bc -mtriple armv7-none-linux-gnueabi -O 3 -rs-debug-ctx -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe'
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so'
build.gradle的相关部分:
renderscriptTargetApi 23
renderscriptSupportModeEnabled true
我搜索了有关 RenderScript 内部工作原理的文档和信息,但它确实很少,因为大多数内部工作原理都留给设备供应商自行决定。
所以我的问题是:是否可以强制 RenderScript 在后台线程上编译脚本,而不阻塞 UI。
感谢任何帮助。
对于遇到此问题的任何人:我设法在应用程序的私有进程中通过服务 运行 解决了这个问题,声明如下:
<service
android:name="com.company.LoadService"
android:process=":loadService"
android:exported="false" />
我在服务中实例化了 ScriptC_something.class-es,因为它是一个单独的进程,所以我的 UI 线程再次空闲。
希望这对某人有所帮助。
我正在开发一个使用自定义 RenderScript 脚本进行图像处理的应用程序。现在,因为我有很多这些脚本在使用中,所以我在应用程序首次启动时预加载它们。 "preload" 我的意思是我实例化每个脚本,以便它可以在设备上编译。下面是这个操作的代码片段。大约有60个脚本,但我认为这足以说明操作。
public class Load extends Thread {
public Load() {
super();
setPriority(Thread.MIN_PRIORITY);
}
@Override
public void run() {
new ScriptC_first(RenderScriptHelper.getInstance());
new ScriptC_second(RenderScriptHelper.getInstance());
new ScriptC_third(RenderScriptHelper.getInstance());
}
}
如您所见,我是在后台线程上执行此操作的。问题是脚本似乎在主线程上编译,不管这个。问题是他们正在阻止 UI。我用 AsyncTask 和 Service 试过这个,结果相同。我怀疑 RenderScript 在内部跳到主线程来编译它们。
现在,在 Android Nougat (7.0) 之前,预加载相同数量的脚本需要不到 10 秒,具体取决于设备速度。在 Nougat 上,这需要将近一分钟的时间,考虑到它会阻止 UI,这是一个大问题,尽管只是在第一次应用程序启动时。在随后的每次启动中,它都会在几秒钟内预加载(因为脚本已经编译)。
我需要预加载,因为按需实例化脚本不是一种选择,因为一旦用户开始使用应用程序,所有脚本都必须准备好并编译。
logcat的相关部分:
E/RenderScript: Unable to open shared library (/data/user/0/com.company.myapp/cache/librs.contrast_v001.so): undefined symbol: .rs.dtor
V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore.bc -mtriple armv7-none-linux-gnueabi -O 3 -load libbccQTI.so -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe'
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so'
此外,如果相关的话,我在第一次启动应用程序时使用 RenderScript.ContextType.PROFILE,在随后的每次启动时使用 RenderScript.ContextType.NORMAL。使用 RenderScript.ContextType.DEBUG 会导致脚本在每次应用程序启动时编译,所用时间与其他上下文相同,并且 logcat 输出略有不同:
V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore_debug.bc -mtriple armv7-none-linux-gnueabi -O 3 -rs-debug-ctx -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe'
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so'
build.gradle的相关部分:
renderscriptTargetApi 23
renderscriptSupportModeEnabled true
我搜索了有关 RenderScript 内部工作原理的文档和信息,但它确实很少,因为大多数内部工作原理都留给设备供应商自行决定。
所以我的问题是:是否可以强制 RenderScript 在后台线程上编译脚本,而不阻塞 UI。
感谢任何帮助。
对于遇到此问题的任何人:我设法在应用程序的私有进程中通过服务 运行 解决了这个问题,声明如下:
<service
android:name="com.company.LoadService"
android:process=":loadService"
android:exported="false" />
我在服务中实例化了 ScriptC_something.class-es,因为它是一个单独的进程,所以我的 UI 线程再次空闲。
希望这对某人有所帮助。