C# MemoryMappedFile

Collection abstraction: squares

MemoryMappedFile provides a performance advantage. It is found in the System.IO.MemoryMappedFiles namespace. It is an abstract data type. It puts a file into memory. It some cases it allows for better memory management than using arrays.

Tip:MemoryMappedFile can be used to improve performance of binary file loading. It was faster than FileStream in all executions.

Example

Performance optimization

First, 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. To do this, the program uses FileStream and then BinaryReader.

And:It uses MemoryMappedFile, MemoryMappedStream, and then BinaryReader. Finally it uses File.ReadAllBytes, MemoryStream and 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
Note

The results of this benchmark are interesting and show that 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.

File.Open

Unfortunately, the program requires a specific binary file that I am not able to share. However, if you want to reproduce the benchmark, you could use any large file and simply read all the bytes in sequentially using BinaryReader.

Summary

C# programming language

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. Careful benchmarking is needed to ensure it is a benefit.

File.ReadAllBytes

Review:MemoryMappedFile, which is only available in .NET 4.0 or later, is ideal for loading binary files in this way.


C#: File