たくさんのアイテムと画像を含むスピナーを備えたアプリケーションがあります。
ユーザーがリストの項目を選択するたびに、多数 (1 ~ 5) の renderscript スクリプトが実行され、画像のピクセルが変更されます。
約 30 の選択を行った後、アプリケーションがエラーでクラッシュします。
これがスタックトレースです。
03-20 13:56:59.366: ERROR/RenderScript(3405): Created fewer than expected number of RS threads.
03-20 13:57:02.990: ERROR/AndroidRuntime(3405): FATAL EXCEPTION: main
java.lang.RuntimeException: createWindowSurface failed EGL_BAD_ALLOC
at android.view.HardwareRenderer$GlRenderer.createSurface(HardwareRenderer.java:1064)
at android.view.HardwareRenderer$GlRenderer.createEglSurface(HardwareRenderer.java:961)
at android.view.HardwareRenderer$GlRenderer.initialize(HardwareRenderer.java:787)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1502)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
renderscript で使用されている不要なスレッドを何らかの形で閉じる必要があると思います。
アップデート:
エラーが異なる場合があります。
03-20 16:09:42.293: ERROR/bcc(24984): !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
03-20 16:09:42.293: ERROR/bcc(24984): rslAssert [frameworks/compile/linkloader/include/ELFObject.h:86] SHNCommonDataPtr && "Must init common data size before use!"
03-20 16:09:42.293: ERROR/bcc(24984): !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
また
03-20 15:46:27.315: ERROR/AndroidRuntime(19330): FATAL EXCEPTION: Thread-3582
android.renderscript.RSRuntimeException: Loading of ScriptC script failed.
at android.renderscript.ScriptC.<init>(ScriptC.java:60)
at com.gfranq.android.ScriptC_BrightnessContrast.<init>(ScriptC_BrightnessContrast.java:41)
at com.gfranq.android.filters.logic.ImageFilter.brightnessContrastRs(ImageFilter.java:1438)
それは行を指します
ScriptC_BrightnessContrast script = new ScriptC_BrightnessContrast(rs, context.getResources(),
R.raw.brightnesscontrast);
更新 2:
これが明るさコントラスト フィルターです。毎回新しい in と out の割り当てと Script オブジェクトを作成すると、メモリが消費されると思います。renderscript アクションのチェーンに 1 つの割り当てを使用することは可能ですか? たとえば、ビットマップから割り当てを行い、次に明るさコントラストフィルターを適用し、次に同様の実装で別のフィルターを適用しますか?
public Bitmap brightnessContrastRs(Bitmap bmIn, int brightness, int contrast, Context context)
{
Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
bmIn.getConfig());
// RenderScript rs = RenderScript.create(context);
Allocation allocIn;
allocIn = Allocation.createFromBitmap(rs, bmIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
Allocation allocOut = Allocation.createTyped(rs, allocIn.getType());
ScriptC_BrightnessContrast script = new ScriptC_BrightnessContrast(rs, context.getResources(),
R.raw.brightnesscontrast);
script.set_in(allocIn);
allocIn.destroy();
script.set_out(allocOut);
script.set_script(script);
float rowContrast = ((100.0f + contrast) * (100.0f + contrast) / 10000.0f);
float rowBrightness = brightness / 255.f;
script.set_rowBrightness(rowBrightness);
script.set_rowContrast(rowContrast);
script.invoke_filter();
allocOut.copyTo(bmOut);
allocOut.destroy();
return bmOut;
}
また、いくつかのアクション内に加えて、かなり大きな int 配列 (360000 int) があります。S criptC オブジェクトを作成するたびに、レンダースクリプト内で定義されたすべての配列にメモリを割り当てるため、メモリがかなり速くリークする可能性があります。
質問を投稿したとき、毎回 RenderScript オブジェクトを作成するコメント行がコメントされておらず、メモリ リークが速くなりました。
端末はnexus4です。
たとえば、これは配列を含む RS ファイルです (他のファイルはこれに似ていますが、配列が含まれていない場合があります)。
rs_allocation out;
rs_allocation in;
rs_script script;
float opacity;
float alphas[360000];
int width;
void root(const uchar4* v_in, uchar4* v_out, const void* usrData, uint32_t x,
uint32_t y)
{
float4 current = rsUnpackColor8888(*v_in);
current.a = alphas[width * y + x] * opacity;
*v_out = rsPackColorTo8888(current.r, current.g, current.b, current.a);
}
void filter()
{
#if !defined(RS_VERSION) || (RS_VERSION < 14)
rsForEach(script, in, out, 0);
#else
rsForEach(script, in, out);
#endif
}