-
Notifications
You must be signed in to change notification settings - Fork 272
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
Collections benchmarks rewrite #92
Conversation
# Conflicts: # src/benchmarks/Benchmarks.csproj
@@ -6,15 +6,15 @@ | |||
<DebugType>pdbonly</DebugType> | |||
<DebugSymbols>true</DebugSymbols> | |||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||
<LangVersion>7.3</LangVersion> | |||
<LangVersion>latest</LangVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call! 👍 #Closed
namespace System.Collections | ||
{ | ||
[BenchmarkCategory(Categories.CoreFX, Categories.Collections, Categories.GenericCollections)] | ||
[GenericTypeArguments(typeof(int))] // value type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorive @ViktorHofer GenericTypeArguments
is the way to tell BDN what T
is for generic classes with benchmarks
{ | ||
private T[] _uniqueValues; | ||
|
||
[Params(Utils.DefaultCollectionSize)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorive @ViktorHofer Params
is the way to parametrize benchmarks per given type, Params can have multiple values like [Params(1, 2, 3)]
but we don't have enough time to run all the benchmarks for more test cases so I am using single, same value everywhere
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Remove="img\**" /> | ||
<EmbeddedResource Remove="img\**" /> | ||
<None Remove="img\**" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="BenchmarkDotNet" Version="0.10.14.667" /> | ||
<PackageReference Include="BenchmarkDotNet" Version="0.10.14.683" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorive I needed to update BDN to have glob filtering support #Closed
I have just pushed the remaining benchmarks for concurrent collections. The PR is ready for final review. |
@adamsitnik How are you selecting the scenarios to benchmark for the generic collections? For example, are we covering the basic ICollection<T> interface? |
@jorive I am using concrete types everywhere, not abstractions. I could add I think that we should have such benchmarks, but I am not sure if they should be part of the @jorive what do you think? |
@adamsitnik That's a good point, and I think that with categories, we could add them to both :) |
public class CtorDefaultSize<T> | ||
{ | ||
[Benchmark] | ||
public T[] Array() => new T[4]; // array has no default size, List has = 4 so I decided to use 4 here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am inclined to remove this test as Array
does not have default Ctor. #ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that we can keep it, the value that it provides to me is comparing the cost of array creation vs the cost of creating array wrappers (list, stack, queue). If the latter is much bigger it means we have a problem #Closed
[Benchmark] | ||
public List<T> List() => new List<T>(Size); | ||
|
||
#if !NET461 // API added in .NET Core 2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should start using #if !NETFRAMEWORK
instead. I can see us adding newer Desktop versions to out matrix. Thoughts? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea! #Closed
{ | ||
internal static T[] GenerateArray<T>(int count) | ||
{ | ||
var random = new Random(12345); // we always use the same seed to have repeatable results! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// we always use the same seed to have repeatable results! [](start = 44, length = 58)
👍 #Closed
|
||
internal static Dictionary<TKey, TValue> GenerateDictionary<TKey, TValue>(int count) | ||
{ | ||
var random = new Random(12345); // we always use the same seed to have repeatable results! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
12345 [](start = 36, length = 5)
nit: Can we make the seed a const
variable used in both methods? #Closed
public int Count; | ||
|
||
[GlobalSetup] | ||
public void Setup() => _uniqueValues = UniqueValuesGenerator.GenerateArray<T>(Count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Feels like Count
here should be replaced with Utils.DefaultCollectionSize
, and Count
on the benchmarks with _uniqueValues.Length
#ByDesign
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am using the value of Param everywhere (not Utils.DefaultCollectionSize) because in the future somebody might like to run this benchmark for more values and then it will require just adding the values to [Param]
[Params(10, 2000, 100000)]
public int Size;
BDN will then run the same benchmark for all provided values (10, 2000, 100000) #Closed
[Benchmark] | ||
public bool Array() | ||
{ | ||
bool result = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please make this loop dependent? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another good point! Done #Closed
@adamsitnik We should open an issue about the loop independent variable assignments. |
@jorive it's on my TODO list, I will start the discussion right after my holidays. (I don;t want to start a discussion and disappear) |
I was supposed to port collections benchmarks.
After digging more into the existing benchmarks I decided to rewrite them instead. Porting them would take a similar amount of time, whereas they would not benefit from all BDN advantages and it would be hard to compare them. Also, many collections (Immutable ones for example) did not have benchmarks at all.