-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Cache GetFileInformationByHandleEx (Length) when FileShare indicates that no one else can change it #49638
Closed
Closed
Cache GetFileInformationByHandleEx (Length) when FileShare indicates that no one else can change it #49638
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
30d8ef7
introduce WindowsFileStreamStrategy
adamsitnik 5c8018d
introduce SyncWindowsFileStreamStrategy
adamsitnik 2e159c4
introduce AsyncWindowsFileStreamStrategy
adamsitnik 5e87d72
some minor improvements after reading the code again
adamsitnik f5c2470
only DerivedFileStreamStrategy needs to have a reference to FileStream
adamsitnik 71e7d43
implement ReadByte and WriteByte to make new windows strategies fully…
adamsitnik 367ad84
implement FlushAsync for no buffering strategies as nop to get Flush_…
adamsitnik 5579e94
use the new strategies when buffering is not enabled
adamsitnik 8bbbcee
introduce BufferedFileStreamStrategy
adamsitnik 9e9cb1f
fix the Mono build
adamsitnik 53752e7
use the Legacy strategy by default for now, add tests for the other i…
adamsitnik e2eec8b
restore old file name to make it easier to review the code (as diff w…
adamsitnik 20640fa
Don't set the buffer to null, to avoid a NullReferenceException
adamsitnik dd7e9ba
fix the browser build?
adamsitnik 2a35ae6
reverting the flushing changes as it looks that they have introduced …
adamsitnik b9afbff
simplify the source code by removing some of the optimizations that a…
adamsitnik 2029317
don't verify OS handle position
adamsitnik f6c8647
track the file offset in memory, don't use expensive sys calls to syn…
adamsitnik 60eedb4
there is no need to set the Length since we are now tracking the offs…
adamsitnik 72a4e94
Cache GetFileInformationByHandleEx (Length) when FileShare does not a…
jozkee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -23,6 +23,8 @@ internal abstract class WindowsFileStreamStrategy : FileStreamStrategy | |||
/// <summary>Whether the file is opened for reading, writing, or both.</summary> | ||||
private readonly FileAccess _access; | ||||
|
||||
private readonly FileShare _share; | ||||
|
||||
/// <summary>The path to the opened file.</summary> | ||||
protected readonly string? _path; | ||||
|
||||
|
@@ -32,6 +34,7 @@ internal abstract class WindowsFileStreamStrategy : FileStreamStrategy | |||
private readonly bool _isPipe; // Whether to disable async buffering code. | ||||
|
||||
private long _appendStart; // When appending, prevent overwriting file. | ||||
private long? _length; | ||||
|
||||
internal WindowsFileStreamStrategy(SafeFileHandle handle, FileAccess access) | ||||
{ | ||||
|
@@ -40,6 +43,7 @@ internal WindowsFileStreamStrategy(SafeFileHandle handle, FileAccess access) | |||
// 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 commentThe reason will be displayed to describe this comment to others. Learn more. instead of using
|
||||
|
||||
// As the handle was passed in, we must set the handle field at the very end to | ||||
// avoid the finalizer closing the handle when we throw errors. | ||||
|
@@ -52,6 +56,7 @@ internal WindowsFileStreamStrategy(string path, FileMode mode, FileAccess access | |||
|
||||
_path = fullPath; | ||||
_access = access; | ||||
_share = share; | ||||
|
||||
_fileHandle = FileStreamHelpers.OpenHandle(fullPath, mode, access, share, options); | ||||
|
||||
|
@@ -77,7 +82,25 @@ internal WindowsFileStreamStrategy(string path, FileMode mode, FileAccess access | |||
|
||||
public sealed override bool CanWrite => !_fileHandle.IsClosed && (_access & FileAccess.Write) != 0; | ||||
|
||||
public unsafe sealed override long Length => FileStreamHelpers.GetFileLength(_fileHandle, _path); | ||||
public unsafe sealed override long Length => _share > FileShare.Read ? | ||||
FileStreamHelpers.GetFileLength(_fileHandle, _path) : | ||||
_length ??= FileStreamHelpers.GetFileLength(_fileHandle, _path); | ||||
|
||||
protected void UpdateLengthOnChangePosition() | ||||
{ | ||||
// Do not update the cached length if the file can be written somewhere else | ||||
// or if the length has not been queried. | ||||
if (_share > FileShare.Read || _length is null) | ||||
{ | ||||
Debug.Assert(_length is null); | ||||
carlossanlop marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
return; | ||||
} | ||||
|
||||
if (_filePosition > _length) | ||||
{ | ||||
_length = _filePosition; | ||||
} | ||||
} | ||||
|
||||
/// <summary>Gets or sets the position within the current stream</summary> | ||||
public override long Position | ||||
|
@@ -256,6 +279,7 @@ protected unsafe void SetLengthCore(long value) | |||
Debug.Assert(value >= 0, "value >= 0"); | ||||
|
||||
FileStreamHelpers.SetLength(_fileHandle, _path, value); | ||||
carlossanlop marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
_length = value; | ||||
|
||||
if (_filePosition > value) | ||||
{ | ||||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
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.
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.