Прежде всего, этот код не работает с сущностями или объектами, поэтому использование ORM вообще не помогает. Это не вызывает OOM, но только делает код на lot медленнее.
Реальная проблема в том, что MemoryStream
на самом деле является оберткой вокруг буфера. Когда буфер заполнен, новый перераспределяется с двойным размером, исходные данные копируются, а старый буфер удаляется. Увеличение буфера размером 50 МБ таким способом приводит к перераспределению lot , log2 (50M). Это фрагментирует свободную память до такой степени, что среда выполнения больше не может выделять достаточно большой непрерывный буфер. Это приводит к тому, что OOM также имеют объекты List<T>
, а не только MemoryStreams.
Быстрое исправление заключается в передаче ожидаемого размера в качестве емкости потока через конструктор MemoryStream (Int32) . Это сокращает перераспределение и , сохраняя много циклов ЦП. Число не обязательно должно быть точным, достаточно большим, чтобы избежать слишком большого количества мусора:
using(Image img = Image.FromFile(file))
using(var imgRes = ResizeImage(img, ImageSettings.Width, ImageSettings.Height))
using(var memoryStream = new MemoryStream(10_000_000))
{
img.Save(memoryStream, ImageFormat.Png);
var label = Directory.GetParent(file).Name;
var bytes = memoryStream.ToArray();
db.Add(new ImageData { Image = bytes, Label = label });
}
Нет необходимости закрывать MemoryStream
, это просто оболочка над массивом. Это все еще выделяет большой буфер для каждого файла.
Если мы знаем максимальный размер файла, мы можем выделить один буфер и использовать его во всех итерациях. В этом случае размер имеет значение - больше невозможно изменить размер буфера:
var buffer=new byte[100_000_000];
using(Image img = Image.FromFile(file))
using(var imgRes = ResizeImage(img, ImageSettings.Width, ImageSettings.Height))
using(var memoryStream = new MemoryStream(buffer))
{
img.Save(memoryStream, ImageFormat.Png);
var label = Directory.GetParent(file).Name;
var bytes = memoryStream.ToArray();
db.Add(new ImageData { Image = bytes, Label = label });
}