私は、約 4000x6000 の画像を (他の多くのタスクの中で) 4 つの部分に分割してイメージできるようにする必要があるサイトに取り組んでおり、これを複数のユーザーに対してできるだけ迅速にする必要があります。
これを行うための私の現在のコードは
var bitmaps = new RenderTargetBitmap[elements.Length];
using (var stream = blobService.Stream(key))
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = stream;
bi.EndInit();
for (var i = 0; i < elements.Length; i++)
{
var element = elements[i];
TransformGroup transformGroup = new TransformGroup();
TranslateTransform translateTransform = new TranslateTransform();
translateTransform.X = -element.Left;
translateTransform.Y = -element.Top;
transformGroup.Children.Add(translateTransform);
DrawingVisual vis = new DrawingVisual();
DrawingContext cont = vis.RenderOpen();
cont.PushTransform(transformGroup);
cont.DrawImage(bi, new Rect(new Size(bi.PixelWidth, bi.PixelHeight)));
cont.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(element.Width, element.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(vis);
bitmaps[i] = rtb;
}
}
for (var i = 0; i < bitmaps.Length; i++)
{
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmaps[i]));
encoder.Save(ms);
var regionKey = WebPath.Variant(key, elements[i].Id);
saveBlobService.Save("image/png", regionKey, ms);
}
}
ジョブをキューから外す複数のスレッドを実行しています。コードのこの部分が一度に 4 つのスレッドにヒットすると、OutOfMemory 例外が発生することがわかりました。上記のすべてのコードを でラップすることで、これを防ぐことができますlock(obj)
が、これは理想的ではありません。最初の using ブロック (ファイルがディスクから読み取られて分割される場所) だけをラップしようとしましたが、それでもメモリ不足の例外が発生します (コードのこの部分は非常に高速に実行されます)。
- これが占めるべきメモリの量を考えると、これは正常ですか?
- 私ができる最適化はありますか?
- 利用可能なメモリを増やすことはできますか?
アップデート:
Moozheのヘルプによる私の新しいコード
public static void GenerateRegions(this IBlobService blobService, string key, Element[] elements)
{
using (var stream = blobService.Stream(key))
{
foreach (var element in elements)
{
stream.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.SourceRect = new Int32Rect(element.Left, element.Top, element.Width, element.Height);
bi.StreamSource = stream;
bi.EndInit();
DrawingVisual vis = new DrawingVisual();
DrawingContext cont = vis.RenderOpen();
cont.DrawImage(bi, new Rect(new Size(element.Width, element.Height)));
cont.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(element.Width, element.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(vis);
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(ms);
var regionKey = WebPath.Variant(key, element.Id);
blobService.Save("image/png", regionKey, ms);
}
}
}
}