-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Cache GetFileInformationByHandleEx (Length) when FileShare indicates that no one else can change it #49638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
remove finalizer from FileStream, keep it only in DerivedFileStreamStrategy and LegacyFileStreamStrategy
… functional they can now be used directly without any buffering on top of them!
…NothingToFlush_CompletesSynchronously passing
…ithin the file, not a removal and addition)
when users have a race condition in their code (i.e. they call Close when calling another method on Stream like Read).
…re not providing too much gains
…llow other processes to modify it
adamsitnik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The perf gains are really impressive!
| // Note: Cleaner to set the following fields in ValidateAndInitFromHandle, | ||
| // but we can't as they're readonly. | ||
| _access = access; | ||
| _share = FileStream.DefaultShare; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of using FileStream.DefaultShare here you can add FileShare share to the ctor arguments and pass FileStream.DefaultShare from FileStream. We are already doing similar thing:
| this(path, mode, access, DefaultShare, DefaultBufferSize, DefaultIsAsync) |
| private readonly bool _isPipe; // Whether to disable async buffering code. | ||
|
|
||
| private long _appendStart; // When appending, prevent overwriting file. | ||
| private long? _length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what would be the difference in the allocated memory if we would use non-nullable long field and use negative values instead null to determine whether the field was initialized or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This field doesn't actually allocate for being nullable; Nullable<T> is a struct, but it makes sense to use negatives instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This field doesn't actually allocate for being nullable
Is sizeof(long) == sizeof(long?)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is sizeof(long) == sizeof(long?)?
Nope, it is 8 and 16 respectively on my machine. I thought you were referring to heap allocations, I will prefer long for the upcoming pull request, thanks.
carlossanlop
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM so far. Questions:
- Do you plan on waiting for Adam's refactoring PR to get merged to avoid any potential conflicts, or are we expecting this PR to get merged first?
- Adam merged his rewrite PR already. Can you please rebase this?
src/libraries/System.Private.CoreLib/src/System/IO/WindowsFileStreamStrategy.cs
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/IO/WindowsFileStreamStrategy.cs
Show resolved
Hide resolved
@carlossanlop I will close this PR and send a new one that combines #49145 and this one, see also #49145 (comment).
For the upcoming PR that I mentioned above, I don't have a preference, if Adam's PR (#49750) gets in first, I can work on fixing the conflics. |
This change builds on top of #49145
Adds caching logic for
GetFileInformationByHandleExwhen the FileStream is constructed withFileShare.ReadorFileShare.None.Fixes #49145
The following benchmark results show ~15-19% gains on
ReadAsyncwhen is indicated to useAsynchronousI/O.I am using the new FileStream implementation (
DOTNET_SYSTEM_IO_USELEGACYFILESTREAM = false).