Skip to content

Improve the performance of BigInteger.{Max|Min}Magnitude/Abs & fix a edge case of TryParse #105570

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

karakasa
Copy link
Contributor

@karakasa karakasa commented Jul 26, 2024

Close #105324

The PR is to:

  • Improve worst-case performance of BigInteger.{Max|Min}Magnitude by changing multiple comparison operators to a single CompareTo call
  • Improve perf of BigInteger.Abs() by refactoring code and making the method branchless.
  • Fix a bug where BigInteger.TryParse still throws instead of returning false.
    • PS: I wrote an OuterLoop test covering this but it would take 1.5~2GB which may unstablize the testing environment. Feel free to notify me if you think the test should be removed. The bug is on a very rare path.
Method Toolchain Length Mean Error StdDev Ratio RatioSD
Abs main 2 2.902 ns 0.0061 ns 0.0048 ns 1.00 0.00
Abs pr 2 1.367 ns 0.0071 ns 0.0059 ns 0.47 0.00
MaxMagnitude_WorstPath main 2 11.603 ns 0.0660 ns 0.0585 ns 1.00 0.00
MaxMagnitude_WorstPath pr 2 3.553 ns 0.0092 ns 0.0081 ns 0.31 0.00
Abs main 16 3.183 ns 0.0133 ns 0.0118 ns 1.00 0.00
Abs pr 16 1.173 ns 0.0433 ns 0.0405 ns 0.37 0.01
MaxMagnitude_WorstPath main 16 14.485 ns 0.3156 ns 0.5690 ns 1.00 0.00
MaxMagnitude_WorstPath pr 16 6.758 ns 0.0230 ns 0.0204 ns 0.46 0.02
Abs main 256 2.912 ns 0.0106 ns 0.0099 ns 1.00 0.00
Abs pr 256 1.138 ns 0.0032 ns 0.0027 ns 0.39 0.00
MaxMagnitude_WorstPath main 256 56.795 ns 0.2398 ns 0.2243 ns 1.00 0.00
MaxMagnitude_WorstPath pr 256 35.709 ns 0.0808 ns 0.0675 ns 0.63 0.00
Abs main 4096 3.007 ns 0.0355 ns 0.0277 ns 1.00 0.00
Abs pr 4096 1.146 ns 0.0181 ns 0.0161 ns 0.38 0.01
MaxMagnitude_WorstPath main 4096 547.978 ns 0.7053 ns 0.5889 ns 1.00 0.00
MaxMagnitude_WorstPath pr 4096 479.951 ns 0.8376 ns 0.7425 ns 0.88 0.00

Improved performance of BigInteger.{Max|Min}Magnitude/Abs/operator-

Co-Authored-By: PetSerAl <17184058+petseral@users.noreply.github.com>
@ghost ghost added the area-System.Numerics label Jul 26, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jul 26, 2024
@karakasa karakasa changed the title Improve the performance of BigInteger.{Max|Min}Magnitude/Abs/operator- Improve the performance of BigInteger.{Max|Min}Magnitude/Abs Jul 27, 2024
@tannergooding tannergooding added this to the 10.0.0 milestone Jul 27, 2024
@karakasa karakasa marked this pull request as ready for review July 28, 2024 08:54
@LEI-Hongfaan
Copy link
Contributor

Interesting.

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private BigInteger(int n, uint[]? rgu, [ConstantExpected] bool noLengthCheck)
        {
            if (noLengthCheck && (rgu is not null) && (rgu.Length > MaxLength))
            {
                ThrowHelper.ThrowOverflowException();
            }

            _sign = n;
            _bits = rgu;

            AssertValid();
        }

https://github.com/LEI-Hongfaan/dotnet-runtime/blob/f49abbbd68a222c0ce77f80aa19ecd53630505e7/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs#L492

And

                    return new BigInteger(-1, buffer, noLengthCheck: true);

https://github.com/LEI-Hongfaan/dotnet-runtime/blob/f49abbbd68a222c0ce77f80aa19ecd53630505e7/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs#L1675

Maybe we can have...

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal BigInteger(int n, uint[]? rgu, [ConstantExpected] bool noLengthCheck = false)

@karakasa
Copy link
Contributor Author

karakasa commented Jul 30, 2024

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal BigInteger(int n, uint[]? rgu, [ConstantExpected] bool noLengthCheck = false)

I tend not to break any existing method, as long as it's not private. ConstantExpected is a good idea.

@huoyaoyuan
Copy link
Member

I tend not to break any existing method, as long as it's not private.

There should not be difference between private and internal in this case. The internal accessors would be dedicated utility types for BigInteger, like the BigIntegerCalculator.

@karakasa karakasa changed the title Improve the performance of BigInteger.{Max|Min}Magnitude/Abs Improve the performance of BigInteger.{Max|Min}Magnitude/Abs & fix a edge case of TryParse Jul 30, 2024
@jeffhandley
Copy link
Member

/azp run runtime-libraries-coreclr outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Numerics community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BigInteger.MaxMagnitude
6 participants