-
Couldn't load subscription status.
- Fork 5.2k
Description
In .NET 6 we have introduced new type called RandomAccess that allows for reading and writing to specific file offset.
As of today, all it's Read* and Write* methods throw when given handle points to a non-seekable file like socket or pipe:
| ThrowHelper.ThrowNotSupportedException_UnseekableStream(); |
But it's not a problem for it's internal implementation (used by FileStream):
runtime/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs
Lines 33 to 38 in d033e1a
| // The Windows implementation uses ReadFile, which ignores the offset if the handle | |
| // isn't seekable. We do the same manually with PRead vs Read, in order to enable | |
| // the function to be used by FileStream for all the same situations. | |
| int result = handle.CanSeek ? | |
| Interop.Sys.PRead(handle, bufPtr, buffer.Length, fileOffset) : | |
| Interop.Sys.Read(handle, bufPtr, buffer.Length); |
And we use it's internal API surface to workaround this limitation is CoreLib (mind the call to RandomAccess.WriteAtOffset (internal), not RandomAccess.Write (public):
| RandomAccess.WriteAtOffset(sfh, bytes, 0); |
We should relax the public requirements and make RandomAccess work with non-seekable files.
This is going to require:
- a breaking change doc
- implementation change (stop throwing exception)
- test changes (this test shows how to easily create a handle that points to non-seekable pipe)
Everything motioned above should be a single PR. In the same or separate PR, the Unix implementation of overloads that accept multiple buffers should start using readv and writev sys-calls. This should be relatively easy (just search for preadv and pwritev and reuse the patterns)
But it's going to allow to:
- switch from heavy
FileStreamto a very lightweightRandomAccesseverywhere where we don't need buffering in BCL (and ofc outside of BCL). Sample perf gains: File.*AllText* optimizations #58167 (comment) - remove a lot of code duplication. Example: https://github.com/dotnet/runtime/blob/main/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.ValueTaskSource.cs