У меня проблема с памятью в приложении flutter, при использовании compute я помещаю эту строку в параметр функции в compute:
var image = imglib.Image.fromBytes(values[1].width, values[1].height, values[1].planes[0].bytes, format: imglib.Format.bgra);
И запустить его в цикле, память продолжает расти каждый раз, затем не хватает памяти и приложение падает.
Если у меня нет этой строки, память стабильна на 40 МБ. Так что я думаю, что в вычислениях он не был очищен после завершения функции вычисления.
У кого-нибудь есть такая же проблема?
Редактировать:
Вот как я реализую вычисления:
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 это пакет изображений:
import 'package:image/image.dart' as imglib;
Каждый раз, когда я это называю, память продолжает расти.
var image
первая строкаgetCropImage(...)
не выпускается после использования, поэтому попробуйте использоватьvar image
поле as (чтобы не всегда выделять новую память), может быть полезно не создавать экземпляр нового var на каждом шаге цикла! Всегда старайтесь повторно использовать эти типы объектов, особенно когда вы управляете большими объектами, такими как изображения. Обычно сборщик мусора не гарантирует освобождение всех неиспользуемых объектов. И помните, никогда не вызывайтеSystem.gc()
или подобные методы напрямую (для принудительного освобождения памяти), это признак неисправного и неоптимизированного кода. :)Ответы:
Чтобы попытаться воспроизвести с вашим образцом, мне пришлось преобразовать из пользовательского интерфейса. Изображение сначала:
Запустите упрощенную версию вашего образца:
Но я не смог увидеть, как память вышла из-под контроля. Так что у вас, вероятно, что-то еще происходит.
источник
Для такого начинающего, как мы, мы должны понимать, что вычислительная функция - это не что иное, как сам изолят. и чем больше вы вызываете для создания изоляции, тем больше памяти вам понадобится. Эта ссылка Spawn Isolates займет ~ 2 Мб оперативной памяти, и поэтому нам нужно сделать изоляторы как можно меньше, даже если вы скажете, что я просто вычисляю и возвращаю результат, поэтому изолят может получить вызов GC, но нет, в то время как вы можете прокручивать и кэширование или выполнение чего-либо с изолятом или вашим кодом в этом изоляте может повлиять на огромный объем памяти.
так что вместо этого я предлагаю вам создать один изолят и делать все, что вы хотите сделать, а когда вы закончите копирование граней, закройте изолят.
Посмотрите это видео, чтобы узнать, как использовать изолят
источник