0

MemoryMappedFile.CreateViewStream(0, len)サイズ のマネージ メモリ ブロックをlen割り当てるか、それともアンマネージ データのスライディング ウィンドウとして機能する小さなバッファを割り当てるか?

今日の MemoryStream であるデシリアライゼーション用の中間バッファーを置き換えることを目指しているため、バッファーのサイズと LOH の断片化の両方のために、大きなデータセットで問題が発生しているのではないかと思います。

ビューストリームの内部バッファが同じサイズになった場合、この切り替えを行っても意味がありません。

編集:

簡単なテストで、MemoryStream と MemoryMapped ファイルを比較すると、これらの数値が見つかりました。GC.GetTotalMemory(true)/1024とからの読みProcess.GetCurrentProcess.VirtualMemorySize64/1024

1GB のメモリ ストリームを割り当てます。

                     Managed           Virtual 
Initial:               81 kB        190 896 kB
After alloc:    1 024 084 kB      1 244 852 kB

予想通り、マネージド メモリと仮想メモリのギグです。次に、MemoryMappedFile について:

                     Managed           Virtual 
Initial:               81 kB        189 616 kB    
MMF allocated:         84 kB        189 684 kB
1GB viewstream allocd: 84 kB      1 213 368 kB
Viewstream disposed:   84 kB        190 964 kB

したがって、あまり科学的ではないテストを使用して、ViewStream は管理されていないデータのみを使用すると仮定しています。正しい?

4

2 に答える 2

2

そのような MMF では問題は解決しません。仮想メモリ空​​間に割り当てに十分な大きさの穴がないため、プログラムは OOM を爆撃します。おわかりのように、MMF で VM アドレス空間をまだ消費しています。

小さなスライド ビューを使用すると回避できますが、それはファイルへの書き込みと何ら変わりはありません。これは、ビューを再マップするときに MMF が行うことであり、ダーティ ページをディスクにフラッシュする必要があります。単純に FileStream にストリーミングすることが適切な回避策です。それでもRAMを使用し、ファイルシステムキャッシュは書き込みを高速化するのに役立ちます. ギガバイトの RAM が利用可能で、最近では入手が難しくない場合、FileStream への書き込みは単なるメモリ間のコピーです。非常に高速で、毎秒 5 ギガバイト以上です。ファイルはバックグラウンドで怠惰な方法で書き込まれます。

Windows では、データをメモリに保持しようとするのは非生産的です。メモリ内のプライベート データはページング ファイルによってバックアップされ、Windows が他のプロセスのために RAM を必要とするときにそのファイルに書き込まれます。そして、再度アクセスしたときに読み返します。それは遅いです。使用するメモリが多いほど、悪化します。デマンド ページ仮想メモリ オペレーティング システムと同様に、ディスクとメモリの違いはわずかです。

于 2013-06-21T16:21:04.113 に答える
0

http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspxの例を考えると、スライド ウィンドウが表示されるように思えます。例。

便宜上、次の例を示します。

    using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;

class Program
{
    static void Main(string[] args)
    {
        long offset = 0x10000000; // 256 megabytes 
        long length = 0x20000000; // 512 megabytes 

        // Create the memory-mapped file. 
        using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))
        {
            // Create a random access view, from the 256th megabyte (the offset) 
            // to the 768th megabyte (the offset plus length). 
            using (var accessor = mmf.CreateViewAccessor(offset, length))
            {
                int colorSize = Marshal.SizeOf(typeof(MyColor));
                MyColor color;

                // Make changes to the view. 
                for (long i = 0; i < length; i += colorSize)
                {
                    accessor.Read(i, out color);
                    color.Brighten(10);
                    accessor.Write(i, ref color);
                }
            }
        }
    }
}

public struct MyColor
{
    public short Red;
    public short Green;
    public short Blue;
    public short Alpha;

    // Make the view brigher. 
    public void Brighten(short value)
    {
        Red = (short)Math.Min(short.MaxValue, (int)Red + value);
        Green = (short)Math.Min(short.MaxValue, (int)Green + value);
        Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
        Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
    }
}
于 2013-06-21T10:57:17.053 に答える