-
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
Attribute for minimal runtime impact during an unmanaged call #30741
Comments
Can you give more explicit guidance on appropriate usage? The examples you give don't give me enough confidence to apply this.
What is a GC transition? What is the benefit that I am foregoing by disabling it?
Does this include a context switch? What happens if there is a page fault?
What is "extensive"? |
CC @AndyAyersMS |
Updated the API with some additional details.
A context switch is most often during a syscall which is mentioned. Exceeding a thread's quantum isn't something that can be predicted so I didn't mention it. A page fault is an interesting question since it can be a syscall. It might be worth adding that allocating memory from the heap should be avoided. I will leave that clarification decision up to @jkotas. |
@JeremyKuhne was thinking about making pinvoke cheaper : probably you already talked. |
@danmosemsft Unfortunately, we have not talked about light weight P/Invokes. I welcome any suggestions here or at dotnet/coreclr#26458. |
Correct. Allocating memory from the heap violates "Native function may execute for a non-trivial amount of time." |
@lambdageek Does this concept make sense for Mono? What would be a good name for it from the Mono point of view? |
@terrajobst Any chance to get this on the API review docket? |
There are a number of cases where this will be helpful. One that just came up for me was getting the current system colors on Windows, which is nothing more than a bounds check and a de-index from an array. We used to cache our own table, firing up a thread to watch for system setting change messages so we could invalidate messages to avoid the call overhead. We now hit the API every time you use a Color that came from a known system color, which in some cases can end up being a lot of unnecessary work. |
Before we review it, I'd like to get some input from the Mono folks. /cc @lambdageek @marek-safar |
Did I get it right that the attribute is valid only in the context of |
At first blush, this: a. it makes sense for Mono; b. has the right restrictions on what the function may do. Need to think about it a bit more.
I've been trying to call them "thread state transitions" rather than "gc state transitions" because we use the same mechanism as part of suspending threads for other reasons (e.g. the soft debugger), but "gc state transition" is much more common in our code. |
|
@marek-safar As @MichalStrehovsky mentioned the @lambdageek What about @jkotas's suggestion of |
I don't like it for all the same reasons that are listed as benefits. 😁 I need to think about what functions with this attribute can do in Xamarin.iOS and Xamarin.Android - I think it's ok to extend the lifetimes of Java or Objective-C objects (if there's a way to do it without an API call), but probably not to shorten them. I wonder if it's worth adding to the restrictions:
So for example some kind of busy wait that requires another thread to toggle some value in shared memory before the current function returns. We've had situations on Linux in Mono where a function in Cooperative mode called the first function from a shared library (ie, we pinvoked So maybe we should also add:
We basically handwaved and pretended like this wasn't happening.
This should be
On Linux, glibc pthreads signalling a condition variable with
For the reasons above, this should really be Questions:
|
@lambdageek Thanks for the feedback.
This attribute has no impact on marshalling of types.
This attribute has no impact on |
How do you define library? |
@lambdageek I have applied some of your suggestions. Please see the updated example above. |
Another naming idea: |
Thanks @jkotas. I have updated the issue with that suggestion as well. |
|
Marshaled delegates have non-trivial by-design overhead. It is not that interesting to make this work for marshaled delegates as performance optimization. The interesting case to make this work as performance optimizations are function pointers. |
@AaronRobinsonMSFT was this feature abandoned? |
@terrajobst Nope. We did this work a while ago dotnet/coreclr#26458. |
Does this mean that conceptually this feature could apply to reverse p/invokes too? Or am I misunderstanding and this statement is only meant to apply to function pointers to unmanaged code? To put it another way: Could |
The
The |
Thanks for the info!
The issues I'm observing are on x64, but I still need to investigate more to determine for sure if |
The constraints on this attribute look very similar to those on the "Fast calls to unmanaged code". Do they work the same way under the hood? |
Yes, the mechanics are similar, with one subtle difference. SuppressGCTransition calls get a GC probe (~2 extra instructions on the hot path, amortized if there is more than one call in the same basic block). FCalls do not do it today that makes them prone to starving GC e.g. if they are called in a loop. #13820 is an example. You can think about the mechanics that we have implemented for these calls as "FCalls done right". We may switch FCalls to get the GC probe in future as well, as we work on improving worst case latencies. |
The work in dotnet/coreclr#26458 is about exposing a way for users to indicate to the runtime that the P/Invoke (unmanaged call) is well-behaved (see API below) enough that the runtime doesn't need to erect a GC transition frame.
Rationale and Usage
There is non-trivial overhead when making a P/Invoke call in the runtime. If the target function is fast enough this overhead can dominate the call rather than the contents of the function. For example, the Win32 function
GetTickCount()
is typically less than 50 instructions however the transition to execute that function is over 60 instructions. This means that setting up to call the function is more expensive than actually running the function itself.There are limits to the benefit here since this does allow the user to create a bad situation where GC starvation, data corruption, or immediate runtime termination can occur. The traditional P/Invoke method via
DllImportAttribute
is designed to ensure all calls are safe with respect to the runtime memory model. This attribute would provide a way to circumvent those guarantees. See the below proposed API for additional details.Community context:
Usage example:
Proposed API
See related PR for complete context. Some alternative names have been proposed that focus on intent rather than implementation detail:
TrivialUnmanagedMethodAttribute
LimitedUnmanagedMethodAttribute
The benefit of focusing on intent is additional optimizations can be enabled with this attribute as they are discovered.
The prototype in the aforementioned PR uses the below proposed API.
/cc @jkotas @stephentoub @jeffschwMSFT @jkoritzinsky
The text was updated successfully, but these errors were encountered: