Skip to content
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

Fix lots of uint[] allocation in BigInteger #46895

Merged
merged 2 commits into from
Jan 14, 2021

Conversation

stephentoub
Copy link
Member

  • Lots of temporary uint[]s are being created and fed into BigInteger's ctor, which then creates a new one. This enables using the input in most cases.
  • GetPartsForBitManipulation is creating uint[]s for small values, after which it generally gets thrown away. Stop doing that.
  • Stack allocation can be used for smaller values in many cases.

Contributes to #44598
Contributes to #22609

Results from the dotnet/performance perf tests...

Method Toolchain numberString arguments Mean Ratio Allocated
Add \master\corerun.exe ? 1024,1024 bits 65.677 ns 1.00 320 B
Add \pr\corerun.exe ? 1024,1024 bits 49.090 ns 0.75 160 B
Subtract \master\corerun.exe ? 1024,1024 bits 65.071 ns 1.00 304 B
Subtract \pr\corerun.exe ? 1024,1024 bits 49.934 ns 0.77 152 B
Multiply \master\corerun.exe ? 1024,1024 bits 849.487 ns 1.00 560 B
Multiply \pr\corerun.exe ? 1024,1024 bits 828.572 ns 0.98 280 B
GreatestCommonDivisor \master\corerun.exe ? 1024,1024 bits 8,411.785 ns 1.00 304 B
GreatestCommonDivisor \pr\corerun.exe ? 1024,1024 bits 8,388.163 ns 1.00 304 B
ModPow \master\corerun.exe ? 1024,1024,64 bits 129,964.288 ns 1.00 304 B
ModPow \pr\corerun.exe ? 1024,1024,64 bits 131,508.269 ns 1.01 304 B
Divide \master\corerun.exe ? 1024,512 bits 516.967 ns 1.00 344 B
Divide \pr\corerun.exe ? 1024,512 bits 503.786 ns 0.97 96 B
Remainder \master\corerun.exe ? 1024,512 bits 522.524 ns 1.00 240 B
Remainder \pr\corerun.exe ? 1024,512 bits 500.804 ns 0.96 240 B
Ctor_ByteArray \master\corerun.exe 123 ? 8.754 ns 1.00 -
Ctor_ByteArray \pr\corerun.exe 123 ? 7.835 ns 0.90 -
ToByteArray \master\corerun.exe 123 ? 12.279 ns 1.00 32 B
ToByteArray \pr\corerun.exe 123 ? 12.302 ns 1.00 32 B
Parse \master\corerun.exe 123 ? 151.144 ns 1.00 104 B
Parse \pr\corerun.exe 123 ? 154.544 ns 1.02 104 B
ToStringX \master\corerun.exe 123 ? 60.100 ns 1.00 32 B
ToStringX \pr\corerun.exe 123 ? 54.792 ns 0.91 32 B
ToStringD \master\corerun.exe 123 ? 36.857 ns 1.00 32 B
ToStringD \pr\corerun.exe 123 ? 37.005 ns 1.01 32 B
ShiftRight \master\corerun.exe 123 ? 22.814 ns 1.00 64 B
ShiftRight \pr\corerun.exe 123 ? 17.989 ns 0.79 -
ShiftLeft \master\corerun.exe 123 ? 20.007 ns 1.00 64 B
ShiftLeft \pr\corerun.exe 123 ? 15.200 ns 0.76 -
Ctor_ByteArray \master\corerun.exe 1234(...)7890 [200] ? 105.972 ns 1.00 112 B
Ctor_ByteArray \pr\corerun.exe 1234(...)7890 [200] ? 103.124 ns 0.97 112 B
ToByteArray \master\corerun.exe 1234(...)7890 [200] ? 56.502 ns 1.00 112 B
ToByteArray \pr\corerun.exe 1234(...)7890 [200] ? 55.041 ns 0.97 112 B
Parse \master\corerun.exe 1234(...)7890 [200] ? 16,713.332 ns 1.00 56584 B
Parse \pr\corerun.exe 1234(...)7890 [200] ? 16,469.686 ns 0.99 55176 B
ToStringX \master\corerun.exe 1234(...)7890 [200] ? 405.306 ns 1.00 360 B
ToStringX \pr\corerun.exe 1234(...)7890 [200] ? 389.472 ns 0.96 360 B
ToStringD \master\corerun.exe 1234(...)7890 [200] ? 1,259.218 ns 1.00 992 B
ToStringD \pr\corerun.exe 1234(...)7890 [200] ? 1,271.013 ns 1.00 992 B
ShiftRight \master\corerun.exe 1234(...)7890 [200] ? 78.992 ns 1.00 224 B
ShiftRight \pr\corerun.exe 1234(...)7890 [200] ? 67.366 ns 0.85 112 B
ShiftLeft \master\corerun.exe 1234(...)7890 [200] ? 60.013 ns 1.00 224 B
ShiftLeft \pr\corerun.exe 1234(...)7890 [200] ? 54.374 ns 0.91 112 B
Add \master\corerun.exe ? 16,16 bits 7.351 ns 1.00 -
Add \pr\corerun.exe ? 16,16 bits 6.254 ns 0.85 -
Subtract \master\corerun.exe ? 16,16 bits 7.110 ns 1.00 -
Subtract \pr\corerun.exe ? 16,16 bits 6.395 ns 0.90 -
Multiply \master\corerun.exe ? 16,16 bits 6.108 ns 1.00 -
Multiply \pr\corerun.exe ? 16,16 bits 6.212 ns 1.02 -
GreatestCommonDivisor \master\corerun.exe ? 16,16 bits 66.017 ns 1.00 -
GreatestCommonDivisor \pr\corerun.exe ? 16,16 bits 66.316 ns 1.00 -
ModPow \master\corerun.exe ? 16,16,16 bits 142.000 ns 1.00 -
ModPow \pr\corerun.exe ? 16,16,16 bits 142.069 ns 1.00 -
Divide \master\corerun.exe ? 16,8 bits 7.470 ns 1.00 -
Divide \pr\corerun.exe ? 16,8 bits 7.864 ns 1.05 -
Remainder \master\corerun.exe ? 16,8 bits 7.333 ns 1.00 -
Remainder \pr\corerun.exe ? 16,8 bits 6.307 ns 0.86 -
ModPow \master\corerun.exe ? 16384,16384,64 bits 2,226,627.204 ns 1.00 2224 B
ModPow \pr\corerun.exe ? 16384,16384,64 bits 2,196,583.036 ns 0.99 2224 B
Divide \master\corerun.exe ? 65536,32768 bits 4,155,074.038 ns 1.00 16473 B
Divide \pr\corerun.exe ? 65536,32768 bits 4,158,249.099 ns 1.00 12345 B
Remainder \master\corerun.exe ? 65536,32768 bits 4,118,120.536 ns 1.00 12337 B
Remainder \pr\corerun.exe ? 65536,32768 bits 4,116,774.665 ns 1.00 12337 B
Add \master\corerun.exe ? 65536,65536 bits 2,470.807 ns 1.00 16448 B
Add \pr\corerun.exe ? 65536,65536 bits 1,888.586 ns 0.76 8224 B
Subtract \master\corerun.exe ? 65536,65536 bits 2,418.995 ns 1.00 16432 B
Subtract \pr\corerun.exe ? 65536,65536 bits 1,881.856 ns 0.78 8216 B
Multiply \master\corerun.exe ? 65536,65536 bits 738,517.936 ns 1.00 169928 B
Multiply \pr\corerun.exe ? 65536,65536 bits 732,919.727 ns 0.99 153520 B
GreatestCommonDivisor \master\corerun.exe ? 65536,65536 bits 4,568,181.194 ns 1.00 16433 B
GreatestCommonDivisor \pr\corerun.exe ? 65536,65536 bits 4,563,006.010 ns 1.00 16433 B
Ctor_ByteArray \master\corerun.exe -2147483648 ? 11.586 ns 1.00 -
Ctor_ByteArray \pr\corerun.exe -2147483648 ? 12.109 ns 1.05 -
ToByteArray \master\corerun.exe -2147483648 ? 13.592 ns 1.00 32 B
ToByteArray \pr\corerun.exe -2147483648 ? 13.372 ns 0.98 32 B
Parse \master\corerun.exe -2147483648 ? 360.580 ns 1.00 136 B
Parse \pr\corerun.exe -2147483648 ? 349.208 ns 0.97 136 B
ToStringX \master\corerun.exe -2147483648 ? 66.486 ns 1.00 40 B
ToStringX \pr\corerun.exe -2147483648 ? 64.597 ns 0.97 40 B
ToStringD \master\corerun.exe -2147483648 ? 72.916 ns 1.00 152 B
ToStringD \pr\corerun.exe -2147483648 ? 69.305 ns 0.95 152 B
ShiftRight \master\corerun.exe -2147483648 ? 31.831 ns 1.00 64 B
ShiftRight \pr\corerun.exe -2147483648 ? 25.519 ns 0.80 -
ShiftLeft \master\corerun.exe -2147483648 ? 24.839 ns 1.00 64 B
ShiftLeft \pr\corerun.exe -2147483648 ? 22.049 ns 0.89 32 B

@stephentoub stephentoub added this to the 6.0.0 milestone Jan 13, 2021
@ghost
Copy link

ghost commented Jan 13, 2021

Tagging subscribers to this area: @tannergooding, @pgovind
See info in area-owners.md if you want to be subscribed.

Issue Details
  • Lots of temporary uint[]s are being created and fed into BigInteger's ctor, which then creates a new one. This enables using the input in most cases.
  • GetPartsForBitManipulation is creating uint[]s for small values, after which it generally gets thrown away. Stop doing that.
  • Stack allocation can be used for smaller values in many cases.

Contributes to #44598
Contributes to #22609

Results from the dotnet/performance perf tests...

Method Toolchain numberString arguments Mean Ratio Allocated
Add \master\corerun.exe ? 1024,1024 bits 65.677 ns 1.00 320 B
Add \pr\corerun.exe ? 1024,1024 bits 49.090 ns 0.75 160 B
Subtract \master\corerun.exe ? 1024,1024 bits 65.071 ns 1.00 304 B
Subtract \pr\corerun.exe ? 1024,1024 bits 49.934 ns 0.77 152 B
Multiply \master\corerun.exe ? 1024,1024 bits 849.487 ns 1.00 560 B
Multiply \pr\corerun.exe ? 1024,1024 bits 828.572 ns 0.98 280 B
GreatestCommonDivisor \master\corerun.exe ? 1024,1024 bits 8,411.785 ns 1.00 304 B
GreatestCommonDivisor \pr\corerun.exe ? 1024,1024 bits 8,388.163 ns 1.00 304 B
ModPow \master\corerun.exe ? 1024,1024,64 bits 129,964.288 ns 1.00 304 B
ModPow \pr\corerun.exe ? 1024,1024,64 bits 131,508.269 ns 1.01 304 B
Divide \master\corerun.exe ? 1024,512 bits 516.967 ns 1.00 344 B
Divide \pr\corerun.exe ? 1024,512 bits 503.786 ns 0.97 96 B
Remainder \master\corerun.exe ? 1024,512 bits 522.524 ns 1.00 240 B
Remainder \pr\corerun.exe ? 1024,512 bits 500.804 ns 0.96 240 B
Ctor_ByteArray \master\corerun.exe 123 ? 8.754 ns 1.00 -
Ctor_ByteArray \pr\corerun.exe 123 ? 7.835 ns 0.90 -
ToByteArray \master\corerun.exe 123 ? 12.279 ns 1.00 32 B
ToByteArray \pr\corerun.exe 123 ? 12.302 ns 1.00 32 B
Parse \master\corerun.exe 123 ? 151.144 ns 1.00 104 B
Parse \pr\corerun.exe 123 ? 154.544 ns 1.02 104 B
ToStringX \master\corerun.exe 123 ? 60.100 ns 1.00 32 B
ToStringX \pr\corerun.exe 123 ? 54.792 ns 0.91 32 B
ToStringD \master\corerun.exe 123 ? 36.857 ns 1.00 32 B
ToStringD \pr\corerun.exe 123 ? 37.005 ns 1.01 32 B
ShiftRight \master\corerun.exe 123 ? 22.814 ns 1.00 64 B
ShiftRight \pr\corerun.exe 123 ? 17.989 ns 0.79 -
ShiftLeft \master\corerun.exe 123 ? 20.007 ns 1.00 64 B
ShiftLeft \pr\corerun.exe 123 ? 15.200 ns 0.76 -
Ctor_ByteArray \master\corerun.exe 1234(...)7890 [200] ? 105.972 ns 1.00 112 B
Ctor_ByteArray \pr\corerun.exe 1234(...)7890 [200] ? 103.124 ns 0.97 112 B
ToByteArray \master\corerun.exe 1234(...)7890 [200] ? 56.502 ns 1.00 112 B
ToByteArray \pr\corerun.exe 1234(...)7890 [200] ? 55.041 ns 0.97 112 B
Parse \master\corerun.exe 1234(...)7890 [200] ? 16,713.332 ns 1.00 56584 B
Parse \pr\corerun.exe 1234(...)7890 [200] ? 16,469.686 ns 0.99 55176 B
ToStringX \master\corerun.exe 1234(...)7890 [200] ? 405.306 ns 1.00 360 B
ToStringX \pr\corerun.exe 1234(...)7890 [200] ? 389.472 ns 0.96 360 B
ToStringD \master\corerun.exe 1234(...)7890 [200] ? 1,259.218 ns 1.00 992 B
ToStringD \pr\corerun.exe 1234(...)7890 [200] ? 1,271.013 ns 1.00 992 B
ShiftRight \master\corerun.exe 1234(...)7890 [200] ? 78.992 ns 1.00 224 B
ShiftRight \pr\corerun.exe 1234(...)7890 [200] ? 67.366 ns 0.85 112 B
ShiftLeft \master\corerun.exe 1234(...)7890 [200] ? 60.013 ns 1.00 224 B
ShiftLeft \pr\corerun.exe 1234(...)7890 [200] ? 54.374 ns 0.91 112 B
Add \master\corerun.exe ? 16,16 bits 7.351 ns 1.00 -
Add \pr\corerun.exe ? 16,16 bits 6.254 ns 0.85 -
Subtract \master\corerun.exe ? 16,16 bits 7.110 ns 1.00 -
Subtract \pr\corerun.exe ? 16,16 bits 6.395 ns 0.90 -
Multiply \master\corerun.exe ? 16,16 bits 6.108 ns 1.00 -
Multiply \pr\corerun.exe ? 16,16 bits 6.212 ns 1.02 -
GreatestCommonDivisor \master\corerun.exe ? 16,16 bits 66.017 ns 1.00 -
GreatestCommonDivisor \pr\corerun.exe ? 16,16 bits 66.316 ns 1.00 -
ModPow \master\corerun.exe ? 16,16,16 bits 142.000 ns 1.00 -
ModPow \pr\corerun.exe ? 16,16,16 bits 142.069 ns 1.00 -
Divide \master\corerun.exe ? 16,8 bits 7.470 ns 1.00 -
Divide \pr\corerun.exe ? 16,8 bits 7.864 ns 1.05 -
Remainder \master\corerun.exe ? 16,8 bits 7.333 ns 1.00 -
Remainder \pr\corerun.exe ? 16,8 bits 6.307 ns 0.86 -
ModPow \master\corerun.exe ? 16384,16384,64 bits 2,226,627.204 ns 1.00 2224 B
ModPow \pr\corerun.exe ? 16384,16384,64 bits 2,196,583.036 ns 0.99 2224 B
Divide \master\corerun.exe ? 65536,32768 bits 4,155,074.038 ns 1.00 16473 B
Divide \pr\corerun.exe ? 65536,32768 bits 4,158,249.099 ns 1.00 12345 B
Remainder \master\corerun.exe ? 65536,32768 bits 4,118,120.536 ns 1.00 12337 B
Remainder \pr\corerun.exe ? 65536,32768 bits 4,116,774.665 ns 1.00 12337 B
Add \master\corerun.exe ? 65536,65536 bits 2,470.807 ns 1.00 16448 B
Add \pr\corerun.exe ? 65536,65536 bits 1,888.586 ns 0.76 8224 B
Subtract \master\corerun.exe ? 65536,65536 bits 2,418.995 ns 1.00 16432 B
Subtract \pr\corerun.exe ? 65536,65536 bits 1,881.856 ns 0.78 8216 B
Multiply \master\corerun.exe ? 65536,65536 bits 738,517.936 ns 1.00 169928 B
Multiply \pr\corerun.exe ? 65536,65536 bits 732,919.727 ns 0.99 153520 B
GreatestCommonDivisor \master\corerun.exe ? 65536,65536 bits 4,568,181.194 ns 1.00 16433 B
GreatestCommonDivisor \pr\corerun.exe ? 65536,65536 bits 4,563,006.010 ns 1.00 16433 B
Ctor_ByteArray \master\corerun.exe -2147483648 ? 11.586 ns 1.00 -
Ctor_ByteArray \pr\corerun.exe -2147483648 ? 12.109 ns 1.05 -
ToByteArray \master\corerun.exe -2147483648 ? 13.592 ns 1.00 32 B
ToByteArray \pr\corerun.exe -2147483648 ? 13.372 ns 0.98 32 B
Parse \master\corerun.exe -2147483648 ? 360.580 ns 1.00 136 B
Parse \pr\corerun.exe -2147483648 ? 349.208 ns 0.97 136 B
ToStringX \master\corerun.exe -2147483648 ? 66.486 ns 1.00 40 B
ToStringX \pr\corerun.exe -2147483648 ? 64.597 ns 0.97 40 B
ToStringD \master\corerun.exe -2147483648 ? 72.916 ns 1.00 152 B
ToStringD \pr\corerun.exe -2147483648 ? 69.305 ns 0.95 152 B
ShiftRight \master\corerun.exe -2147483648 ? 31.831 ns 1.00 64 B
ShiftRight \pr\corerun.exe -2147483648 ? 25.519 ns 0.80 -
ShiftLeft \master\corerun.exe -2147483648 ? 24.839 ns 1.00 64 B
ShiftLeft \pr\corerun.exe -2147483648 ? 22.049 ns 0.89 32 B
Author: stephentoub
Assignees: -
Labels:

area-System.Numerics, tenet-performance

Milestone: 6.0.0

- Lots of temporary uint[]s are being created and fed into BigInteger's ctor, which then creates a new one.  This enables using the input in most cases.
- GetPartsForBitManipulation is creating uint[]s for small values, after which it generally gets thrown away.  Stop doing that.
- Stack allocation can be used for smaller values in many cases.
@stephentoub stephentoub merged commit c0038ab into dotnet:master Jan 14, 2021
@stephentoub stephentoub deleted the bigintalloc branch January 14, 2021 18:46
@danmoseley
Copy link
Member

Contributes to #44598

@stephentoub that's interesting, is BigInteger in startup paths somewhere?

@stephentoub
Copy link
Member Author

stephentoub commented Jan 15, 2021

that's interesting, is BigInteger in startup paths somewhere?

Yes, not the runtime itself, but as part of ASP.NET https development certificate generation on first run.

@danmoseley
Copy link
Member

danmoseley commented Jan 15, 2021

Do you have something like an aggregated trace of where time is spent/allocations happen during the various startup paths we care about? I wonder whether it might be interesting to list the top places of interest in #44598 or somewhere to crowd source community interest in optimizing some places like this.

@ghost ghost locked as resolved and limited conversation to collaborators Feb 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants