-
-
Notifications
You must be signed in to change notification settings - Fork 984
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
High differences between run for GC Diagnoser #133
Comments
I have been running our integration tests plenty of times, they contain simple test for GC Diagnoser and the results were always the same. .NET GC is selftunning (changing Gen sizes etc) but we always start new process so the results should be almost the same as long as OS has similar resources available. Could you give some sample benchmark with config that you use? |
Can you post the logs from 2 runs with different # of GC collections? It'll be easier to see what's going on On 1 Apr 2016, at 02:48, "Alexandre Mutel" notifications@github.com wrote:
|
The output I'm getting while running multiple times is like this:
As you can see, sometimes figures are jolting for the Gem0/Gen1/Gen2 (worse for Bytes Allocated/Op), changing even the ranking between runs. When I'm running for example a simple benchmark (without using BenchmarkDotNet) and outputing |
Looking at the code, one thing I'm not sure is that I would expect the GCDiagnoser to only process GC events for the IterationMode.MainTarget period: Typically there are other periods that seem to be non deterministic (like the IdleTarget, not sure what it does, but it looks like it is adapting to the process) and we don't want them as part of the measurement. Also, not sure that it is good to have variable #operation count for different method when measuring GC events... |
Ok, so after trying to tweak the usage of BenchmarkDotNet and using Though, not sure I did use correctly the API, but I had to patch the I used the following config: var config = ManualConfig.Create(DefaultConfig.Instance);
var gcDiagnoser = new GCDiagnoser();
config.Add(new Job { Mode = Mode.SingleRun, LaunchCount = 2, WarmupCount = 2, TargetCount = 10 });
config.Add(gcDiagnoser); |
The Gen 0/1/2 values are scaled/normalised based on the min value across the benchmarks (see https://github.com/PerfDotNet/BenchmarkDotNet/blob/master/BenchmarkDotNet.Diagnostics/GCDiagnoser.cs#L174), so it's not surprising they vary as the # of runs/Ops changes. However the # Bytes is per Op, so should be more stable |
Yeah 'OperationsPerInvoke' isn't going to help, that's for something else.
Good point, I need to have a think about how to best handle this. |
Setting
It results in only 1 op:
|
Looking at MethodInvoker.cs:92 , |
Also on a side note, I had to compile |
Hm, ok, maybe Diagnostics cannot be released because |
Hmm, didn't realise that @adamsitnik or @AndreyAkinshin does this block us from releasing a BenchmarkDotNet.Diagnostics nuget package? |
@xoofx are you happy with the workaround you have, i.e. using a custom Or would you want BenchmarkDotNet to be more stable/consistent across runs? |
Actually, I was able to ship native DLLs
Hm, actually, no as I said above, |
|
ah, ok 😅, but how does it translate to a fixed count then? Not sure to understand the meaning of this parameter... |
Back on the subject, so any way to run for all benchmarks the same count of loop (I guess SingleRun mode, with no setup/pilot phase) to have a predictible test with MemoryDiagnoser? I tried var config = ManualConfig.Create(DefaultConfig.Instance);
var gcDiagnoser = new MemoryDiagnoser();
config.Add(new Job { Mode = Mode.SingleRun, LaunchCount = 2, WarmupCount = 2, IterationTime = 1024, TargetCount = 10 });
config.Add(gcDiagnoser); But doesn't not work... Very annoying, as so far, I can't have reliable test with GC. If you have a workaround without modifying the code, that would help, thanks! |
For reference, the patch I used to get stable results |
@AndreyAkinshin, what are your thoughts on this, what's a safe way to make the # of As a test I added the following line of code:
And across 3 runs I got the following:
This is the problem, the total number of Currently @xoofx uses the config below, plus this patch
What's the best way to get this behaviour into BenchmarkDotNet in a reliable way? What about if we explicitly set |
What you can do there is normalize everything. The Bytes Allocated/Op will be similar (no reason it should change over multiple runs) so normalization can give you a single value that is the average of all them. |
I'm not sure that just normalising them will help here, because unless I'm mistaken what you're proposing, we already do that? In MemoryDiagnoser.cs we have this code: return (result.AllocatedBytes / (double)result.TotalOperations).ToString("N2"); |
Trying to play with the GCDiagnoser and I'm getting weird results on consecutive run, like the Gen0/Gen1/Gen2/Bytes Allocated/Op are varying a lot (30-40%), making it quite useless to compare... while I would not expect figures to change that much (afaik, I'm not aware about this indeterministic GC behaviour)
Have you been noticing this issue or Am I doing something wrong there?
The text was updated successfully, but these errors were encountered: