-
Notifications
You must be signed in to change notification settings - Fork 230
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
Rule S6608: Benchmark is benchmarking the wrong things #9390
Comments
Hi @Apollo3zehn, Thanks for the feedback. Designing a good benchmark is not an easy task and it's easy to fall into all kinds of traps :) I think the current approach, in the case of I see your point that Our first thought to improve this was to use a predefined list of randomly generated numbers (done in the setup), but that would also mean accessing arrays twice in each of the benchmarked methods. Leading again to numbers greater than they actually are. Another approach we considered was to use a pseudo-number generator fast enough to not affect the numbers too much and still provide a degree of randomness. An example would be the one invented by George Marsaglia. We ended up with the simple solution, the one you suggested that removes the calls to the random number generator. On the PC I use, the numbers look like this, which I agree is more consistent when providing a general view of all the benchmarked methods.
I do have a question about the returning value. I'm not sure if it makes a difference, as we are also assigning the retrieved value in the current implementation. I did a test and the numbers look very similar:
The last example is the one without a return statement. Do you have more context about this? Or is there something that I'm missing? |
That was also my first idea and then I came to the same conclusion :-)
In the current implementation you assign the variable to a discard variable ( I agree that there is not difference in this specific benchmark with the current .NET 8 compiler but that might change without us noticing. |
I got a S6608 warning using SolarLink in VSCode and ran the benchmark referenced in the documentation.
The result is:
The results suggest that
ElementAt
andIndex
are slow methods but the actual problem is that on every loop iteration one random value is being generated which is much slower than the actual array access:sonar-dotnet/analyzers/rspec/cs/S6608.html
Line 174 in c8fc28e
A simple benchmark tells me that
random.Next(0, SampleSize)
itself takes around7000 ns
so it has a huge impact on the actual benchmark results. Withoutrandom.Next(0, SampleSize)
the methodElementAt
becomes much less slow andIndex
is on par withFirst_Index
andLast_Index
.The modified code is shown below. The only disadvantage of not using a random index is that now the CPU cache is being used in an optimal way which makes the result look a bit better than for a real random access.
To avoid the risk of code being optimized out I added a return value to all benchmark methods (https://fransbouma.github.io/BenchmarkDotNet/RulesOfBenchmarking.htm#avoid-dead-code-elimination).
The text was updated successfully, but these errors were encountered: