Skip to content

[Perf] BigInteger formatting performance regression in .NET 9 #111708

@xakep139

Description

@xakep139

Description

After reading Performance Improvements in .NET 9 related to BigInteger, I've noticed a comment indicating that C# has poor performance compared to other programming languages in terms of big integer calculations. After quick investigation, it turned out that half of the time in https://github.com/hanabi1224/Programming-Language-Benchmarks/blob/main/bench/algorithm/edigits/1.cs is spent on formatting of a big integer. On .NET 8 it's done twice as fast, even though there were performance optimizations made in .NET 9.

Here's a benchmark code that shows the issue:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Numerics;

BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

[MemoryDiagnoser(false)]
[HideColumns("Job", "Error", "StdDev", "Median", "RatioSD")]
public class Tests
{
    private char[] _dest = new char[1_000_000];

    private BigInteger _value =
        BigInteger.Pow(BigInteger.Parse(string.Concat(Enumerable.Repeat("1234567890", 30))), 1_000);

    [Benchmark(Baseline = true)]
    public string Stringify() => _value.ToString();

    [Benchmark]
    public bool TryFormat() => _value.TryFormat(_dest, out _);
}

Configuration

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.2894)
AMD Ryzen 9 4900H with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.102
  [Host]     : .NET 8.0.12 (8.0.1224.60305), X64 RyuJIT AVX2
  Job-TESATW : .NET 8.0.12 (8.0.1224.60305), X64 RyuJIT AVX2
  Job-VBXNCI : .NET 9.0.1 (9.0.124.61010), X64 RyuJIT AVX2

Regression?

Yes. The same code on .NET 8 executes ~3 times faster (but with much more memory being allocated).

Data

| Method    | Runtime  | Mean    | Ratio | Allocated | Alloc Ratio |
|---------- |--------- |--------:|------:|----------:|------------:|
| Stringify | .NET 8.0 | 1.009 s |  1.00 | 1303.9 KB |       1.000 |
| TryFormat | .NET 8.0 | 1.005 s |  1.00 | 719.71 KB |       0.552 |
| Stringify | .NET 9.0 | 3.657 s |  3.62 | 585.23 KB |       0.449 |
| TryFormat | .NET 9.0 | 3.657 s |  3.63 |   1.05 KB |       0.001 |

Analysis

This regression might be caused by the #100181, but I haven't thoroughly tested that regression on older codebase.
The regression is reproduced on really big integers (order of magnitude 1000+).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-System.Numericsin-prThere is an active PR which will close this issue when it is mergedtenet-performancePerformance related issueuntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions