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

BigInteger constructor perf #91176

Merged
merged 6 commits into from
Nov 3, 2023
Merged

BigInteger constructor perf #91176

merged 6 commits into from
Nov 3, 2023

Conversation

Rob-Hague
Copy link
Contributor

@Rob-Hague Rob-Hague commented Aug 27, 2023

Use BinaryPrimitives/MemoryMarshal in BigInteger constructor

Method Job ByteCount IsBigEndian Mean Error StdDev Ratio Code Size
Ctor pr 5 False 13.28 ns 0.073 ns 0.065 ns 1.05
Ctor main 5 False 12.60 ns 0.067 ns 0.063 ns 1.00
Ctor pr 5 True 16.38 ns 0.036 ns 0.032 ns 1.32
Ctor main 5 True 12.37 ns 0.016 ns 0.013 ns 1.00
Ctor pr 16 False 11.78 ns 0.019 ns 0.018 ns 0.66
Ctor main 16 False 17.72 ns 0.113 ns 0.094 ns 1.00
Ctor pr 16 True 15.08 ns 0.059 ns 0.055 ns 0.84
Ctor main 16 True 17.90 ns 0.015 ns 0.012 ns 1.00
Ctor pr 64 False 13.78 ns 0.022 ns 0.019 ns 0.31
Ctor main 64 False 44.43 ns 0.040 ns 0.036 ns 1.00
Ctor pr 64 True 17.45 ns 0.027 ns 0.021 ns 0.39
Ctor main 64 True 44.82 ns 0.040 ns 0.033 ns 1.00
Ctor pr 256 False 22.16 ns 0.020 ns 0.017 ns 0.15
Ctor main 256 False 150.99 ns 0.240 ns 0.213 ns 1.00
Ctor pr 256 True 28.29 ns 0.031 ns 0.027 ns 0.18
Ctor main 256 True 153.63 ns 0.862 ns 0.806 ns 1.00
public class Benchmark
{
    [Params(5, 16, 64, 256)]
    public int ByteCount;

    [Params(true, false)]
    public bool IsBigEndian;

    private byte[] _bytes;

    [GlobalSetup]
    public void Setup()
    {
        Random r = new(123);
        _bytes = new byte[ByteCount];
        do
        {
            r.NextBytes(_bytes);
            // Use positive benchmark values for consistency
        } while (_bytes[0] is not (> 0 and < 0x80) || _bytes[^1] is not (> 0 and < 0x80));
    }

    [Benchmark] public BigInteger Ctor() => new BigInteger(_bytes, isBigEndian: IsBigEndian);
}

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Aug 27, 2023
@ghost
Copy link

ghost commented Aug 27, 2023

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

Use BinaryPrimitives/MemoryMarshal in BigInteger constructor


BenchmarkDotNet v0.13.7, Windows 11 (10.0.22621.2134/22H2/2022Update/SunValley2)
AMD Ryzen 7 5700U with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK 8.0.100-preview.7.23376.3
  [Host]     : .NET 7.0.4 (7.0.423.11508), X64 RyuJIT AVX2
  pr : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2
  main : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2


Method Job ByteCount IsBigEndian Mean Error StdDev Median Ratio RatioSD
Ctor pr 5 False 16.87 ns 0.201 ns 0.178 ns 16.87 ns 1.12 0.01
Ctor main 5 False 15.11 ns 0.051 ns 0.045 ns 15.10 ns 1.00 0.00
Ctor pr 5 True 10.35 ns 0.050 ns 0.044 ns 10.34 ns 0.82 0.00
Ctor main 5 True 12.68 ns 0.026 ns 0.020 ns 12.67 ns 1.00 0.00
Ctor pr 16 False 11.39 ns 0.010 ns 0.008 ns 11.39 ns 0.63 0.01
Ctor main 16 False 17.95 ns 0.370 ns 0.396 ns 17.66 ns 1.00 0.00
Ctor pr 16 True 12.75 ns 0.268 ns 0.251 ns 12.74 ns 0.71 0.01
Ctor main 16 True 17.86 ns 0.132 ns 0.103 ns 17.82 ns 1.00 0.00
Ctor pr 64 False 25.55 ns 0.151 ns 0.118 ns 25.50 ns 0.48 0.01
Ctor main 64 False 53.89 ns 0.894 ns 0.836 ns 54.34 ns 1.00 0.00
Ctor pr 64 True 22.35 ns 0.036 ns 0.030 ns 22.36 ns 0.50 0.00
Ctor main 64 True 44.86 ns 0.049 ns 0.038 ns 44.84 ns 1.00 0.00
Ctor pr 256 False 48.89 ns 0.062 ns 0.058 ns 48.87 ns 0.27 0.00
Ctor main 256 False 183.99 ns 0.502 ns 0.419 ns 183.79 ns 1.00 0.00
Ctor pr 256 True 60.14 ns 0.115 ns 0.096 ns 60.11 ns 0.39 0.00
Ctor main 256 True 153.37 ns 0.081 ns 0.068 ns 153.36 ns 1.00 0.00
    public class Benchmark
    {
        [Params(5, 16, 64, 256)]
        public int ByteCount;

        [Params(true, false)]
        public bool IsBigEndian;

        private byte[] _bytes;

        [GlobalSetup]
        public void Setup()
        {
            Random r = new(123);
            _bytes = new byte[ByteCount];
            r.NextBytes(_bytes);
        }

        [Benchmark] public BigInteger Ctor() => new BigInteger(_bytes, isBigEndian: IsBigEndian);
    }
Author: Rob-Hague
Assignees: -
Labels:

area-System.Numerics

Milestone: -

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall it LGTM, but I would prefer another set of eyes that is more familiar with endianness conversion to confirm that.

@Rob-Hague thank you for your contribution!

@adamsitnik adamsitnik self-assigned this Oct 30, 2023
@adamsitnik adamsitnik added the tenet-performance Performance related issue label Oct 30, 2023
@stephentoub
Copy link
Member

/azp list

Copy link

CI/CD Pipelines for this repository:

@stephentoub
Copy link
Member

/azp run runtime-community

Copy link

Azure Pipelines successfully started running 1 pipeline(s).


// Copy all dwords, except don't do the last one if it's not a full four bytes
int curDword, curByte;
int wholeDwordCount = Math.DivRem(byteCount, 4, out int unalignedBytes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use:

(uint wholeUInt32Count, uint unalignedBytes) = Math.DivRem((uint)byteCount, 4);

instead, since we know here byteCount isn't negative?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we did, then we would have to cast the values back to int in each of the AsSpan and Slice calls. What do you suggest?

@Rob-Hague
Copy link
Contributor Author

Commenting the runtime-community build link in case it disappears when I push

https://dev.azure.com/dnceng-public/public/_build/results?buildId=456533&view=results

@adamsitnik
Copy link
Member

/azp run runtime-community

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the s390x failures are unrelated (they are being addressed by #94333)

@adamsitnik adamsitnik merged commit 5becf0f into dotnet:main Nov 3, 2023
112 of 115 checks passed
@Rob-Hague Rob-Hague deleted the bigintctor branch November 3, 2023 14:53
@EgorBo
Copy link
Member

EgorBo commented Nov 7, 2023

@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Numerics community-contribution Indicates that the PR has been added by a community member tenet-performance Performance related issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants