Skip to content

Commit

Permalink
Use RandomAccess/File.OpenHandle in a few more places (#55150)
Browse files Browse the repository at this point in the history
Places where we don't need to pay for the FileStream and the access pattern is easily replaced.
  • Loading branch information
stephentoub authored Jul 9, 2021
1 parent c90aa4d commit fe9005f
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 31 deletions.
36 changes: 13 additions & 23 deletions src/libraries/System.Private.CoreLib/src/System/IO/File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;

#if MS_IO_REDIST
using System;
Expand Down Expand Up @@ -373,19 +374,13 @@ public static void WriteAllBytes(string path, byte[] bytes)
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));

InternalWriteAllBytes(path, bytes);
}

private static void InternalWriteAllBytes(string path, byte[] bytes)
{
Debug.Assert(path != null);
Debug.Assert(path.Length != 0);
Debug.Assert(bytes != null);

using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
fs.Write(bytes, 0, bytes.Length);
}
#if MS_IO_REDIST
using FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
fs.Write(bytes, 0, bytes.Length);
#else
using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read);
RandomAccess.WriteAtOffset(sfh, bytes, 0);
#endif
}
public static string[] ReadAllLines(string path)
{
Expand Down Expand Up @@ -836,22 +831,17 @@ private static async Task<byte[]> InternalReadAllBytesUnknownLengthAsync(FileStr

return cancellationToken.IsCancellationRequested
? Task.FromCanceled(cancellationToken)
: InternalWriteAllBytesAsync(path, bytes, cancellationToken);
}

private static async Task InternalWriteAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken)
{
Debug.Assert(!string.IsNullOrEmpty(path));
Debug.Assert(bytes != null);
: Core(path, bytes, cancellationToken);

using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, DefaultBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan))
static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken)
{
#if MS_IO_REDIST
using FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, 1, FileOptions.Asynchronous | FileOptions.SequentialScan);
await fs.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false);
#else
await fs.WriteAsync(new ReadOnlyMemory<byte>(bytes), cancellationToken).ConfigureAwait(false);
using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous | FileOptions.SequentialScan);
await RandomAccess.WriteAtOffsetAsync(sfh, bytes, 0, cancellationToken).ConfigureAwait(false);
#endif
await fs.FlushAsync(cancellationToken).ConfigureAwait(false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.Win32.SafeHandles;

namespace System.IO
{
Expand All @@ -25,10 +26,10 @@ public static void CopyFile(string sourceFullPath, string destFullPath, bool ove
}

// Copy the contents of the file from the source to the destination, creating the destination in the process
using (var src = new FileStream(sourceFullPath, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, FileOptions.None))
using (var dst = new FileStream(destFullPath, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, DefaultBufferSize, FileOptions.None))
using (SafeFileHandle src = File.OpenHandle(sourceFullPath, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None))
using (SafeFileHandle dst = File.OpenHandle(destFullPath, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.None))
{
Interop.CheckIo(Interop.Sys.CopyFile(src.SafeFileHandle, dst.SafeFileHandle));
Interop.CheckIo(Interop.Sys.CopyFile(src, dst));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ private static unsafe int WriteSyncUsingAsyncHandle(SafeFileHandle handle, ReadO
}
}

private static ValueTask<int> ReadAtOffsetAsync(SafeFileHandle handle, Memory<byte> buffer, long fileOffset, CancellationToken cancellationToken)
internal static ValueTask<int> ReadAtOffsetAsync(SafeFileHandle handle, Memory<byte> buffer, long fileOffset, CancellationToken cancellationToken)
=> handle.IsAsync
? Map(QueueAsyncReadFile(handle, buffer, fileOffset, cancellationToken))
: ScheduleSyncReadAtOffsetAsync(handle, buffer, fileOffset, cancellationToken);
Expand Down Expand Up @@ -269,7 +269,7 @@ internal static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int error
return (vts, -1);
}

private static ValueTask<int> WriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemory<byte> buffer, long fileOffset, CancellationToken cancellationToken)
internal static ValueTask<int> WriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemory<byte> buffer, long fileOffset, CancellationToken cancellationToken)
=> handle.IsAsync
? Map(QueueAsyncWriteFile(handle, buffer, fileOffset, cancellationToken))
: ScheduleSyncWriteAtOffsetAsync(handle, buffer, fileOffset, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Text;
using System.Threading;
using System.Security;
using Microsoft.Win32.SafeHandles;

namespace System
{
Expand Down Expand Up @@ -615,16 +616,17 @@ private static bool CompareTimeZoneFile(string filePath, byte[] buffer, byte[] r
try
{
// bufferSize == 1 used to avoid unnecessary buffer in FileStream
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1))
using (SafeFileHandle sfh = File.OpenHandle(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
if (stream.Length == rawData.Length)
long fileLength = RandomAccess.GetLength(sfh);
if (fileLength == rawData.Length)
{
int index = 0;
int count = rawData.Length;

while (count > 0)
{
int n = stream.Read(buffer, index, count);
int n = RandomAccess.Read(sfh, buffer.AsSpan(index, count), index);
if (n == 0)
ThrowHelper.ThrowEndOfFileException();

Expand Down

0 comments on commit fe9005f

Please # to comment.