Flutterアプリの分離にメモリの問題はありますか?


9

フラッターアプリのメモリに関する問題があり、computeを使用する場合は、computeの関数パラメーターに次の行を追加します。

var image = imglib.Image.fromBytes(values[1].width, values[1].height, values[1].planes[0].bytes, format: imglib.Format.bgra);

そしてそれをループで実行すると、メモリが毎回増え続け、その後メモリが不足し、アプリがクラッシュしました。

そのラインがない場合、メモリは40MBで安定しています。ですから、コンピューティングでは、コンピューティング関数の終了後はクリーンアップされていないと思います。

誰もが同じ問題を抱えていますか?

編集:

これは私がコンピューティングを実装する方法です:

image = await compute(getCropImage, [copyFaces, streamImg]);

getCropImageで:

Future<imglib.Image> getCropImage(List<dynamic> values) async {
  var image = imglib.Image.fromBytes(values[1].width, values[1].height, values[1].planes[0].bytes, format: imglib.Format.bgra);

  double topLeftX = values[0][0].boundingBox.topLeft.dx.round() -
  (values[0][0].boundingBox.width * 0.2);
  double topLeftY = values[0][0].boundingBox.topLeft.dy.round() -
  (values[0][0].boundingBox.height * 0.2);
  double width = values[0][0].boundingBox.width.round() +
  (values[0][0].boundingBox.width * 0.4);
  double height = values[0][0].boundingBox.height.round() +
  (values[0][0].boundingBox.height * 0.4);
  if (topLeftX <= 0) {
    topLeftX = 25;
  }
  if (topLeftY <= 0) {
    topLeftY = 25;
  }
  if ((topLeftX + width) >= values[1].width) {
    width = values[1].width - topLeftX - 25;
  }
  if ((topLeftY + height) >= values[1].height) {
    height = values[1].height - topLeftY - 25;
  }

  return imglib.copyCrop(
      image, topLeftX.round(), topLeftY.round(), width.round(), height.round());
}

imglibはImageパッケージです。

import 'package:image/image.dart' as imglib;

これを呼び出すたびに、メモリは増え続けます。


より多くのコードを共有できますか?特に計算方法。
Esen Mehmet、

編集中にコードを追加しました。チェックしてください。返信ありがとうございます。@EsenMehmet
hoangquyy

計算方法とは何ですか?imglibとは何ですか?詳細を追加してください。
Igor Kharakhordin

あなたはここでコンピューティングメソッドを読むことができます:api.flutter.dev/flutter/foundation/compute.html、それは私の実装機能ではありません、私はそれを使用します。imglibはパッケージイメージ:pub.dev/packages/imageです。すみません、私の悪い@IgorKharakhordin
hoangquyy

1
私はと思うvar imageの1行目にgetCropImage(...)そう使用してみて、使用後にリリースされていませんvar image(常に新しいメモリを割り当てないようにするために)フィールドとして、おそらくすべてのループステップで新しいVARをインスタンス化しないように役立ちます!特に画像などの大きなオブジェクトで管理している場合は、常にこれらのタイプのオブジェクトを再利用するようにしてください。通常、ガベージコレクターは、未使用のオブジェクトをすべて解放することを保証しません。また、System.gc() (メモリの割り当て解除を強制するために)直接または同様のメソッドを呼び出さないでください。これは、壊れたコードで最適化されていないコードの症状です。:)
Roberto Manfreda

回答:


0

あなたのサンプルで再現しようとするために、私は最初にui.Imageから変換しなければなりませんでした:

Future<Uint8List> _bytePng(ui.Image image) async {
  ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
  Uint8List byteList = byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes);
  return byteList;
}

サンプルの簡易バージョンを実行します。

imglib.Image image2 = await compute(_getImage, [image1.width, image1.height, byteList]);


Future<imglib.Image> _getImage(List<dynamic> values) async {
  var temp = imglib.Image.fromBytes(values[0], values[1], values[2], format: imglib.Format.bgra);

  var rng = new Random().nextInt(50);
  imglib.Image cropped = imglib.copyCrop(temp, 0, 0, temp.width - rng, temp.height - rng);

  return cropped;
}

しかし、私は記憶が暴走するのを見ることができませんでした。したがって、おそらく何か他のことが起こっています。


プロファイルモードでメモリを確認しましたか?どのバージョンのフラッターを使用していますか?確かではありませんが、フラッターバージョンから来たのかもしれません。誰かが私と同じ問題を抱えている: - stackoverflow.com/questions/57826962/...
hoangquyy


だから問題は私のコードから来たのではないと思います。この問題を解決するために他の方法を使用しましたが、分離を使用しなくなりました。ただし、ありがとうございます。このメモリの問題を解決することは良いことです。
hoangquyy

0

私たちのような初心者にとって、計算機能は分離そのものにすぎないことを理解する必要があります。作成するために呼び出す回数が増えるほど、必要なメモリが多くなります。この参照 Isolates spawnには2 MBのRAMがかかる ため、計算して結果を返していると言っても、分離を可能な限り少なくする必要があるため、分離はGC呼び出しを取得する可能性がありますが、一度にスクロールすることはできません分離またはその分離内のコードを使用してキャッシュまたは何かを行うと、メモリ内の巨大なフットプリントに影響を与える可能性があります。

そうするよりも、1つの分離を作成し、やりたいことをすべて実行することをお勧めします。すべての作業が終了したら、面をコピーして分離を閉じます。

このビデオを見て、分離の使用方法を知る

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.