简体   繁体   中英

Renderscript ScriptC compile blocking main thread

I'm working on an app which uses custom RenderScript scripts for image processing. 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. There are about 60 scripts, but I thought this was enough to illustrate the operation.

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. I suspect that RenderScript internally hops on the main thread to compile them.

Now, prior to Android Nougat (7.0), preloading the same amount of scripts took under 10 seconds depending on the device speed. 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. 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:

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. 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:

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:

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.

So my question is: is it possible to force RenderScript to compile scripts on the background thread, without blocking the 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.

Hope this helps someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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