.Net 内存映射优化
起因
在获取.Net源码,发现对内存映射文件进行了优化,这个改进很简单,只是减少了对文件是否存在的检查.这一块代码是使用模式匹配.public static MemoryMappedFile CreateFromFile(string path, FileMode mode, string? mapName, long capacity,
MemoryMappedFileAccess access)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (mapName != null && mapName.Length == 0)
{
throw new ArgumentException(SR.Argument_MapNameEmptyString);
}
if (capacity < 0)
{
throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired);
}
if (access < MemoryMappedFileAccess.ReadWrite ||
access > MemoryMappedFileAccess.ReadWriteExecute)
{
throw new ArgumentOutOfRangeException(nameof(access));
}
if (mode == FileMode.Append)
{
throw new ArgumentException(SR.Argument_NewMMFAppendModeNotAllowed, nameof(mode));
}
if (mode == FileMode.Truncate)
{
throw new ArgumentException(SR.Argument_NewMMFTruncateModeNotAllowed, nameof(mode));
}
if (access == MemoryMappedFileAccess.Write)
{
throw new ArgumentException(SR.Argument_NewMMFWriteAccessNotAllowed, nameof(access));
}
// bool existed = File.Exists(path);
//改为模式匹配,减少对文件是否存在的检查,在使用完毕,如果是这里创建的文件,要把文件删除
bool existed = mode switch
{
FileMode.Open => true, // FileStream ctor will throw if the file doesn't exist
FileMode.CreateNew => false,
_ => File.Exists(path)
};
FileStream fileStream = new FileStream(path, mode, GetFileAccess(access), FileShare.Read, 0x1000, FileOptions.None);
if (capacity == 0 && fileStream.Length == 0)
{
CleanupFile(fileStream, existed, path);
throw new ArgumentException(SR.Argument_EmptyFile);
}
if (capacity == DefaultSize)
{
capacity = fileStream.Length;
}
SafeMemoryMappedFileHandle? handle;
try
{
handle = CreateCore(fileStream, mapName, HandleInheritability.None,
access, MemoryMappedFileOptions.None, capacity);
}
catch
{
CleanupFile(fileStream, existed, path);
throw;
}
Debug.Assert(handle != null);
Debug.Assert(!handle.IsInvalid);
return new MemoryMappedFile(handle, fileStream, false); //内部调用系统api(Windows是MapViewOfFile,Linux是mmap)
}
// clean up: close file handle and delete files we created
private static void CleanupFile(FileStream fileStream, bool existed, string path)
{
fileStream.Dispose();
if (!existed)
{
File.Delete(path);
}
}
秋风
2022-01-16