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
Proposal: improve System.Guid performance with LayoutKind.Explicit and static arrays #27990
Comments
I forgot to mention that my parsing implementation rejects strings like these:
System.Guid implementation accepts such strings. P.S. It's hard for me to imagine using such patterns in real-world applications... |
It's fine to change the implementation to improve performance, so feel free to submit a PR along with the associated measurements, but we should not break compatibility (even if some behaviors seem odd) without a really good reason, so all of the Guid tests need to continue to pass. |
It would probably be ok though if parsing unlikely cases like |
|
@stephentoub,@danmosemsft, @jkotas, I was thinking of making an adaptation for arm64 later. |
Those, and the GuidTests.netcoreapp.cs file, are the main tests we have specific to Guid. But we could of course have test gaps. And there could be other corefx test suites exercising Guid indirectly. CI in coreclr will run all of the corefx tests, including those (subject to the platform limitations @jkotas called out). |
Is adding 2K of static data in corelib a good idea? |
Our CI system runs tests on ARM64. You can submit WIP PR to see whether the change passes on ARM64 and other platforms. Note that this change would need to be submitted through https://github.com/dotnet/coreclr repo. The Guid implementation is in CoreLib that is part of the runtime. |
Also, for parsing, make sure you're comparing against the latest in master rather than against .NET Core 2.1. dotnet/coreclr#20183 improved Guid parsing perf (though not to the same degree your metrics above cite, but maintaining compatibility). |
Thank you! Can I ask you a couple more questions? I have read Contributing to .NET Core / Contributing to mscorlib library and saw this recommendation:
|
That guideline is outdated/confusing - the right repo to submit this change to is CoreCLR.
We try to minimize the amount of platform specific code in the implementation, even if that means losing a tiny bit of performance. If you can show that the custom layout per platform has very large performance advantage, we can consider it, but I doubt that it will be the case for Guid. |
Updated in dotnet/coreclr#21201 |
Thank you. I think I'll postpone the PR for I'll think about how to adapt |
That is... unfortunate. Maybe we should have a |
There is: TryParseExact with any of the formats other than X is very strict... X is just more forgiving than you'd expect. |
More precisely, other than "X" and "D". My examples above assume format "D". Maybe it is worth adding two more strict formats (with other letters)? |
Ah, I forgot about D. Which also means the others except for N. |
:) What do you think about adding strict formats? |
I've not heard of the existing ones causing any actual problems, and while it's great to make things as fast as possible, parsing perf is already significantly improved for 3.0, and it's not clear to me that introducing new formats to make it much faster will significantly move the needle on any real workloads. I'd want to see evidence of real apps suffering before we invested in additional formats. |
I did not mean performance. I'll adapt my changes to existing logic. For me, the problem is input data validation. For example, "00000000-0x00-+123-0000-000000000000" is not what I expect from input data in my projects. |
Is this likely? and if so how would you detect it? I've got a vectorised version of Equals which is 50% faster but it would need to be able to detect this in a jit const way to get the speedup effectively. |
I do not know the details (I decided to adapt the parsing first and such detection is not required for parsing). I made my conclusions based on this answer by @jkotas:
|
Looking at the current Equals implementation I don't think it would be correct if all platforms didn't have a contiguous layout. It calculates offsets from the first field which would be incorrect if there were ever padding. Even though the layout is sequential the fields are all blittable and can be obviously packed as they are, I'd be surprised if anything required more space. |
Guid is 16 bytes on all platforms and it is not going to change. I was talking specifically about breaking nature of adding fields and ExplicitLayout for interop because that is what the FastGuid prototype has done. It added fields but have not changed Guid size. |
Thank you for the clarification! |
I added PR dotnet/runtime#22465. The results of all the checks I will find out tomorrow. I'm not sure when I will be available, so I apologize in advance if I can’t quickly respond to comments. |
Should I do something else with the PR dotnet/runtime#22465? |
Unfortunately, PR is too unstable in term of performance in different environments. |
Thank you for working on it! |
I am not sure about possibility to use LayoutKind.Explicit for System.Guid and to add several fields, although all proposed changes are (binary) compatible with current implementation. That's why I made a separate repository with several benchmarks.
Are these changes acceptable? If yes, I'll try to write a pull request.
Changes details
Equals
andCompareTo
methods. 16 (byte) fields added forToString
andTryParseExact
methods.Equals
andCompareTo
methods have become faster due to less comparisons (with less fields).ToString
andTryParseExact
methods have become faster due to using static arrays.Benchmarks
System.Guid
methods, "Uuid" — forFastGuid.Uuid
methods.Equals
benchmark results too good because of aggressive inlining (can be slower when inlining not available).CompareTo
andEquals
two benchmarks used for each struct to see the difference between comparing the same and different identifiers.CompareTo
andEquals
appropriate methods called thrice like_guid1.CompareTo(_guid2) ^ _guid2.CompareTo(_guid3) ^ _guid3.CompareTo(_guid1)
.ToString
last letter means one of the standard guid formats — D, B, N or X.CompareTo
Equals
ToString
TryParseExact
The text was updated successfully, but these errors were encountered: