简体   繁体   English

Renderscript ScriptC编译阻塞主线程

[英]Renderscript ScriptC compile blocking main thread

I'm working on an app which uses custom RenderScript scripts for image processing. 我正在开发一个使用自定义RenderScript脚本进行图像处理的应用程序。 Now, since i have a lot of these scripts in use I preload them on apps first start. 现在,由于我有很多这些脚本在使用,我首先在应用程序上预加载它们。 By "preload" i mean that I instantiate each script so that it would compile on the device. 通过“预加载”我的意思是我实例化每个脚本,以便它可以在设备上编译。 Bellow is the code snippet of this operation. Bellow是此操作的代码片段。 There are about 60 scripts, but I thought this was enough to illustrate the operation. 大约有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());
    }
}

As you can see, I am doing this on a background thread. 如您所见,我在后台线程上执行此操作。 Problem is that scripts seem to compile on main thread regardless of this. 问题是脚本似乎在主线程上编译,无论如何。 Issue is they are blocking the UI. 问题是他们阻止了用户界面。 I have tried this with AsyncTask and Service with the same result. 我用AsyncTask和Service尝试了相同的结果。 I suspect that RenderScript internally hops on the main thread to compile them. 我怀疑RenderScript内部在主线程上跳转以编译它们。

Now, prior to Android Nougat (7.0), preloading the same amount of scripts took under 10 seconds depending on the device speed. 现在,在Android Nougat(7.0)之前,根据设备速度预加载相同数量的脚本花费不到10秒。 On Nougat it takes near a minute which is a huge issue considering it's blocking the UI, albeit only on the first app start. 在Nougat上花了近一分钟这是一个巨大的问题,考虑到它阻止了UI,尽管只是在第一个应用程序启动时。 On every subsequent starts it preloads under a few seconds (because scripts are already compiled). 在每次后续启动时,它会在几秒钟内预加载(因为脚本已经编译)。

I need preloading because instantiating scripts on demand is not an option, since all scripts have to be ready and compiled once the user starts using the app. 我需要预加载,因为根据需要实例化脚本不是一个选项,因为一旦用户开始使用应用程序,所有脚本都必须准备好并进行编译。

Relevant portion of the logcat: 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'

Also, if relevant i am using RenderScript.ContextType.PROFILE on first app start and RenderScript.ContextType.NORMAL on each subsequent start. 此外,如果相关,我在第一个应用程序启动时使用RenderScript.ContextType.PROFILE,并在每个后续启动时使用RenderScript.ContextType.NORMAL。 Using RenderScript.ContextType.DEBUG causes scripts to compile on each app start, taking the same amount of time as the other contexts, and logcat output is slightly different: 使用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'

Relevant portions of build.gradle: build.gradle的相关部分:

renderscriptTargetApi 23
renderscriptSupportModeEnabled true

I searched the docs and information on RenderScript inner workings, but it is really scarce, as most of the inner workings are left to device vendors discretion. 我搜索了有关RenderScript内部工作的文档和信息,但它非常缺乏,因为大多数内部工作都由设备供应商自行决定。

So my question is: is it possible to force RenderScript to compile scripts on the background thread, without blocking the UI. 所以我的问题是:是否可以强制RenderScript在后台线程上编译脚本,而不会阻止UI。

Any help is appreciated. 任何帮助表示赞赏。

For anyone who comes across this problem: I managed to solve the issue with a service running in private process of the app, declared as such: 对于遇到此问题的任何人:我设法通过在应用程序的私有进程中运行的服务来解决问题,声明如下:

<service
    android:name="com.company.LoadService"
    android:process=":loadService"
    android:exported="false" />

I instantiated the ScriptC_something.class-es inside the service, and since it's a separate process, my UI thread is free once more. 我在服务中实例化ScriptC_something.class-es,因为它是一个单独的进程,我的UI线程再次免费。

Hope this helps someone. 希望这有助于某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM