BenchmarkDotnet.linq AllocatedBytes Bug
AllocatedBytes was always null
using the built-in benchmark tooling. The cause was the following line:TotalAllocatedBytes += g.GetTotalAllocatedBytes(false) ?? 0;
With the type of Nullable<int>
defaulting to null
, the compound operator was resolving to TotalAllocatedBytes = null + (g.GetTotalAllocatedBytes(false) ?? 0);
, thus always null
I updated the code in my instance to the following and it is now working as intended:
struct MemoryStats { public long TotalOperations { get; private set; } public long? TotalAllocatedBytes { get; private set; } public long? BytesPerOperation => TotalOperations == 0 ? null : TotalAllocatedBytes / TotalOperations; public void Record(GcStats g) { TotalOperations += g.TotalOperations; var totalAllocatedBytes = g.GetTotalAllocatedBytes(false) ?? 0; if (TotalAllocatedBytes is null) TotalAllocatedBytes = totalAllocatedBytes; else TotalAllocatedBytes += totalAllocatedBytes; } }
Comments
What was the code before you changed it?
Mine doesn't define TotalAllocatedBytes as nullable so I don't see any issues with it.
My version was
long?
to begin with. My LinqPad version is 8.6.1, which is reported as the latest. But I'm not sure how updates to the linq file are handled.I considered changing the type to non-nullable as the fix. But I didn't want to go through and find any potential side-effects. So it makes sense to me that Joe wrote it as
long
in another version.That is the same LinqPad version that I am using.
At the top of the script there is a comment that says that changes are merged in (and I have seen that happen)
I've made a few changes to my copy of BenchmarkDotNet, so to make sure I hadn't changed MemoryStats, I
compared my current query with the default embedded in Linqpad , using
That is strange - I think
TotalAllocatedBytes
has always been non-nullable. At one stage there existed some other condition that could cause that figure to report incorrectly, but that was patched some time ago.That's interesting. To my recollection I have never modified the file until making this post. The diff of my local versus embedded version has this difference in the reference section that might point to something:
I archived my local and restored the assembly version. Thanks for all the help.
I should also mention that if you ever want to do a reset, you can delete the file and LINQPad will recreate it.