Skip to content
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

Merged
merged 32 commits into from
Jul 20, 2018

Conversation

adamsitnik
Copy link
Member

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.

# 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>
Copy link
Member

@jorive jorive Jul 13, 2018

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
Copy link
Member Author

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)]
Copy link
Member Author

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" />
Copy link
Member Author

@adamsitnik adamsitnik Jul 13, 2018

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

@adamsitnik
Copy link
Member Author

I have just pushed the remaining benchmarks for concurrent collections. The PR is ready for final review.

@jorive
Copy link
Member

jorive commented Jul 17, 2018

@adamsitnik How are you selecting the scenarios to benchmark for the generic collections? For example, are we covering the basic ICollection<T> interface?

@adamsitnik
Copy link
Member Author

@jorive I am using concrete types everywhere, not abstractions.

I could add ICollection<T> , IReadOnlyCollection<T>, IDictionary<T> , IReadOnlyDictionary<T> cases but I would be benchmarking more or less the used collection type + virtual method dispatch overhead.

I think that we should have such benchmarks, but I am not sure if they should be part of the System.Collections benchmarks or CoreClr.Virtualization

@jorive what do you think?

@jorive
Copy link
Member

jorive commented Jul 18, 2018

@adamsitnik That's a good point, and I think that with categories, we could add them to both :)
I just wanted to understand the cases that we are covering and make sure we have the basics too, for example: insert, remove, find?

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
Copy link
Member

@jorive jorive Jul 18, 2018

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

Copy link
Member Author

@adamsitnik adamsitnik Jul 19, 2018

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
Copy link
Member

@jorive jorive Jul 18, 2018

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

Copy link
Member Author

@adamsitnik adamsitnik Jul 19, 2018

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!
Copy link
Member

@jorive jorive Jul 18, 2018

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!
Copy link
Member

@jorive jorive Jul 18, 2018

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);
Copy link
Member

@jorive jorive Jul 18, 2018

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

Copy link
Member Author

@adamsitnik adamsitnik Jul 19, 2018

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;
Copy link
Member

@jorive jorive Jul 18, 2018

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

Copy link
Member Author

@adamsitnik adamsitnik Jul 19, 2018

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

@jorive
Copy link
Member

jorive commented Jul 19, 2018

@adamsitnik We should open an issue about the loop independent variable assignments.

@adamsitnik adamsitnik merged commit 2b3bd56 into dotnet:master Jul 20, 2018
@adamsitnik
Copy link
Member Author

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants