.Net 内存映射优化

起因

在获取.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