You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MetadataReader ReadFile fast path does not work with async file streams #14276
When a FileStream is opened with isAsync: true (.NET Core default!), the ReadFile P/Invoke code that we have in the metadata reader to read small files straight to native memory. ReadFile fails with invalid param error code because our handle was opened for overlapped IO.
For now, I'm changing the code to be more defensive and always fall back to the slow file -> managed heap -> native heap code path. (It currently throws.)
@ericstj: Can you help me figure out how to tweak FileStreamReadLightUp.cs to handle this?
Also, @tmat has already mentioned to me that this code path will slow us down on Linux and Mac. Perhaps, this is the right opportunity to define a portable FileStream.Read overload that reads to unmanaged memory?
@ericstj I don't control the construction of the FileStream. The reader tries to light up and do a fast read via P/Invoke on the Stream that gets passed in already constructed.
In that case you never know if you are getting a sync or overlapped handle. The fact that the default changed is irrelevant since it could have happened before. The way to detect it is to do a ReadFile specifying null for overlapped and see if it fails with ERROR_INVALID_PARAMETER. See VerifyHandleIsSync. You could fallback to actually doing the overlapped IO rather than falling back to managed heap.
I realize this could have happened before, I just meant that the new default is why it was only uncovered now. I'll look into doing the overlapped IO, but this code is getting gnarly as it has to worry about running on non-Windows.
I'd like to talk some more about having a Stream.Read into byte* with an efficient override in FileStream that just does the right thing. If we think we'll do that, I'd rather wait for that than make this light-up code any more complex.
I'd have to benchmark to see if this is even worth it. We only go down this path for files of size <= 16KB...
Activity
ericstj commentedon Feb 23, 2015
If you are getting the handle out of FileStream you should pass all arguments to the FileStream constructor (Either UseAsync or FileOptions).
nguerrera commentedon Feb 23, 2015
@ericstj I don't control the construction of the FileStream. The reader tries to light up and do a fast read via P/Invoke on the Stream that gets passed in already constructed.
ericstj commentedon Feb 23, 2015
In that case you never know if you are getting a sync or overlapped handle. The fact that the default changed is irrelevant since it could have happened before. The way to detect it is to do a ReadFile specifying null for overlapped and see if it fails with ERROR_INVALID_PARAMETER. See VerifyHandleIsSync. You could fallback to actually doing the overlapped IO rather than falling back to managed heap.
nguerrera commentedon Feb 24, 2015
I realize this could have happened before, I just meant that the new default is why it was only uncovered now. I'll look into doing the overlapped IO, but this code is getting gnarly as it has to worry about running on non-Windows.
I'd like to talk some more about having a Stream.Read into byte* with an efficient override in FileStream that just does the right thing. If we think we'll do that, I'd rather wait for that than make this light-up code any more complex.
I'd have to benchmark to see if this is even worth it. We only go down this path for files of size <= 16KB...
nguerrera commentedon Dec 2, 2015
dotnet/corefx#4786 tracks the BCL feature that could make all of this code go away from S.R.Metadata.
karelz commentedon Nov 11, 2016
This looks tricky. Where to start is mentioned above.