-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Buffer::BlockCopy may spend too long without GC polling #13554
Comments
This. We have prior art in CoreRT. I will give it a shot |
Would be interesting to compare, in mono we emit @llvm.memmove intrinsic for Buffer.BlockCopy (and we ask llvm to place safepoints for us) |
Do you have safepoints inside the loop that @llvm.memmove expands into when the length is not constant? |
@jkotas just checked, unfortunately we don't, llvm is able to unroll it for small constants but otherwise it converts it into a libc call so the problem remains. UPD: However, there is an ability to expand memmove into loops ( |
The Is this something that CoreRT was handling? |
That is handled in both CoreCLR and CoreRT. Both delegate to CRT for blocks over certain size (with a proper PInvoke frame that avoids the GC starvation problem). |
* Rewrite Buffer.BlockCopy in C# Fixes #27106 * Workaround to enable type check optimizations for BlockCopy only
Keeping this open to fix other places where we do large copies in cooperative mode. |
This is fixed for all memory copy variants exposed by the framework now. We have other similar problems for sure. I have opened dotnet/coreclr#27683 on one found via codereview. Also, @adamsitnik is going to run experiment to see whether Benchmark.NET can be used to find these types of issues. |
I've performed the experiment and shared my results in dotnet/performance#1049 |
Buffer::BlockCopy
is an FCALL that delegates to the nativememmove
which may spend a lot of time there depending on how much is being copied.If GC needs to sync with user threads at inconvenient time, everything will stop until the
memmove
is done. GC would wait formemmove
, everything else will wait for GC.There was an actual scenario reported when GC pauses could take up to a minute due to this.
(dealing with very large streams, potentially swapped out, ...)
We should either "chunk" large copying into smaller pieces with intermittent GC polling, or just move the whole thing to managed code.
The text was updated successfully, but these errors were encountered: