C# MemoryMappedFile Example

Use MemoryMappedFile and CreateViewStream. A benchmark is provided.
MemoryMappedFile. This type provides a performance advantage. It is found in the System.IO.MemoryMappedFiles namespace. It is an abstract data type.
With MemoryMappedFile, we put a file into memory. In some cases it allows for better memory management than using arrays. MemoryMappedFile improves performance of binary file loading.
A simple start. Let's try just loading a file into a memory mapping. Make sure you create the "test.file" and add some characters to it. Then we load it into a mapping.

Zeros: The ReadByte method returns zeros after the content of the text file. So we can stop processing when zeros are encountered.

Note: For an important program, we would want better looping behavior to know the precise end of the data.

C# program that uses MemoryMappedFile, CreateViewStream using System; using System.IO.MemoryMappedFiles; class Program { static void Main() { using (MemoryMappedFile file = MemoryMappedFile.CreateFromFile("c:\\programs\\test.file")) using (MemoryMappedViewStream stream = file.CreateViewStream()) { while (true) { // Read in byte from the MemoryMappedFile. int result = stream.ReadByte(); // Zero bytes are past the end of the file. if (result == 0) { break; } // Print file data to the console. Console.WriteLine("NUMBER: " + result); char letter = (char)result; Console.WriteLine("LETTER: " + letter); } } } } Contents (test.file): HELLO Output NUMBER: 72 LETTER: H NUMBER: 69 LETTER: E NUMBER: 76 LETTER: L NUMBER: 76 LETTER: L NUMBER: 79 LETTER: O
Benchmark. This program loads a binary file of 4.37 MB that contains binary data. The file is essentially a grouping of about 1400 smaller files.

Tip: To do this, the program uses FileStream and then BinaryReader. It uses MemoryMappedFile, MemoryMappedStream, and then BinaryReader.

C# program that benchmarks MemoryMappedFile using System; using System.Diagnostics; using System.IO; using System.IO.MemoryMappedFiles; class Program { static void Main() { const int max = 1; var s1 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { Test1(); } s1.Stop(); var s2 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { Test2(); } s2.Stop(); var s3 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { Test3(); } s3.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) / max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) / max).ToString("0.00 ns")); Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000 * 1000) / max).ToString("0.00 ns")); } static void Test1() { // FileStream. using (FileStream file = File.Open("C:\\P.bin", FileMode.Open)) { Read(file); } } static void Test2() { // MemoryMappedFile. using (MemoryMappedFile file = MemoryMappedFile.CreateFromFile("C:\\P.bin")) using (MemoryMappedViewStream stream = file.CreateViewStream()) { Read(stream); } } static void Test3() { // MemoryStream. using (MemoryStream stream = new MemoryStream(File.ReadAllBytes("C:\\P.bin"))) { Read(stream); } } static void Read(Stream stream) { // This method reads in the file-format specific values. using (BinaryReader reader = new BinaryReader(stream)) { int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { string u = reader.ReadString(); int len = reader.ReadInt32(); byte[] b = reader.ReadBytes(len); } } } } Results when max is 1: 9671400.00 ns 6737300.00 ns 6958400.00 ns Results when max is 100: 7246513.00 ns 4726050.00 ns 7294708.00 ns
Notes, benchmark. MemoryMappedFile is fast. For loading the file only once, MemoryMappedFile is faster than the other two approaches. The FileStream approach is the slowest.

And: For loading the file 100 times, MemoryMappedFile is somewhat less than twice as fast as the other approaches.


Note: The program requires a binary file. To reproduce, use any large file and read all the bytes in sequentially using BinaryReader.

A summary. MemoryMappedFile provides a way to load a file with good performance. It seems to have better performance than FileStream and also the File.ReadAllBytes approach.File.ReadAllBytes
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to