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
Very slow in those type of calcs #92184
Comments
Seems to be an issue with Given |
To be precise, most time is spent in |
These benchmark games are not necessarily representative of real world workloads. Nor do they always implement code the idiomatic way nor do they always do them the best way. There are improvements that could be made to Python largely only has 3 numeric types: On the other hand, C#/.NET has many numeric types with different precisions and signedness: C#/.NET are correspondingly optimized around this fact and it is often expected that you select the right data type for your scenario, rather than solely relying on Much in the same way since Java doesn't have This allows C#/.NET users more control and often the ability to achieve overall better perf when you select the right tool for the job. Simple naive transpilation is often not sufficient nor a good representation of language performance. |
While that's true @tannergooding most of the benchmarks are using a big integer implementation so it looks pretty fair from that POV. I agree that it's unclear if it's real-world benchmark but if there's low hanging fruit in big integer this might be the motivation to improve it. |
Yes. BigInteger needs a full rewrite eventually, but it's much lower priority compared to other work. The two key considerations are:
Accounting for the readonly factor would likely make the large factor in the perf here |
We have a higher perf mutable and inline buffer based BigInteger we use internally for things like floating-point parsing and formatting |
If there's a work item on BigInteger performance, we can link to these benchmarks. |
Unfortunately explanations like "i's not real world scenario" and similar are not fully true Good example is this simple code I did So potential hope for new version 9.0 about BigInteger improvements.
|
Maybe, but it's also possible they would use a different number type when using C#. That's not an excuse, but this isn't the only to do calculations in C# as @tannergooding mentioned. |
That's why I called it "fully" because partially I can agree with tannergooding |
The intent wasn't to say that using Microbenchmarks are, as the name implies, "micro". They are often a very small piece of the overall picture and may often have various constraints around the inputs/outputs that do not align with how you might use such code in a fully integrated production environment. As I mentioned, Python primarily performs better in this particular case because they only have However, in .NET, It is, of course, still important we optimize it further. But its prioritization may differ from other languages accordingly. And that when we optimize, we take a look at what the microbenchmark is doing and if it looks represenative of the work a non static scenario would need to compute. -- For example, using We are aware of some efforts that are needed to improve For this scenario the biggest issue is that The other factor is that our The primary solution to the first factor would be to provide a The primary solution to the second factor would be to rewrite the implementation of Neither of these are trivial tasks and would require significant work. The first would require API design and review, while the latter would simply require someone to do the implementation and review it. There are notably some other more minor improvements that could be done as well. But they would be overall less impactful outside targeted scenarios like this. As an examples, we could provide a specialization for |
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsNet (all versions, 6, 7 and coming 8 are all very slow compared to other languages) https://programming-language-benchmarks.vercel.app/problem/edigits I'm not sure if this will work there, but this is a suggestion for possible optimisations.
|
Tagging subscribers to this area: @dotnet/area-system-numerics Issue DetailsNet (all versions, 6, 7 and coming 8 are all very slow compared to other languages) https://programming-language-benchmarks.vercel.app/problem/edigits I'm not sure if this will work there, but this is a suggestion for possible optimisations.
|
BCryptEncrypt which admittedly is super optimized for the case it cares about ... but still, it's about 7 times faster than equivalent math using BigInteger. I've pasted this gist that compares two implementations https://gist.github.com/mjsabby/b87b629fa902cd641b955892b1ab9604 |
This issue may be fixed in #96895.
benchmark codeusing BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Configs;
using System.Numerics;
using System.Runtime.InteropServices;
[DisassemblyDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)]
public class PerformanceTest
{
[Benchmark]
[Arguments(100000)]
[Arguments(250001)]
public string Run(int n)
{
var result = new System.Text.StringBuilder();
var k = BinarySearch(n);
var (p, q) = SumTerms(0, k - 1);
p += q;
var a = BigInteger.Pow(new BigInteger(10), n - 1);
var answer = p * a / q;
var answerStr = answer.ToString();
Span<char> sb = stackalloc char[10];
for (var i = 0; i < n; i += 10)
{
var count = i + 10;
if (count > n)
{
count = n;
}
for (var j = i; j < i + 10; j++)
{
if (j < n)
{
sb[j - i] = answerStr[j];
}
else
{
sb[j - i] = ' ';
}
}
result.AppendLine($"{new String(sb)}\t:{count}");
}
return result.ToString();
}
static (BigInteger, BigInteger) SumTerms(int a, int b)
{
if (b == a + 1)
{
return (new BigInteger(1), new BigInteger(b));
}
var mid = (a + b) / 2;
var (pLeft, qLeft) = SumTerms(a, mid);
var (pRight, qRight) = SumTerms(mid, b);
return (pLeft * qRight + pRight, qLeft * qRight);
}
static int BinarySearch(int n)
{
var a = 0;
var b = 1;
while (!TestK(n, b))
{
a = b;
b *= 2;
}
while (b - a > 1)
{
var m = (a + b) / 2;
if (TestK(n, m))
{
b = m;
}
else
{
a = m;
}
}
return b;
}
static bool TestK(int n, int k)
{
if (k < 0)
{
return false;
}
var lnKFactorial = k * (Math.Log((double)k) - 1) + 0.5 * Math.Log(Math.PI * 2);
var log10KFactorial = lnKFactorial / Math.Log(10);
return log10KFactorial >= (double)(n + 50);
}
} |
Net (all versions, 6, 7 and coming 8 are all very slow compared to other languages)
I do not expect to be as fast as e.g. rust, but being 10x slower than slow python is a bit of a shame:
https://programming-language-benchmarks.vercel.app/problem/edigits
I'm not sure if this will work there, but this is a suggestion for possible optimisations.
Hope that version 9 will do something with that.
The text was updated successfully, but these errors were encountered: