Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions src/ObjectPool/perf/Microbenchmarks/DrainRefillMultiTheaded.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;

namespace Microsoft.Extensions.ObjectPool.Microbenchmarks;

[MemoryDiagnoser]
public class DrainRefillMultiTheaded
{
private DefaultObjectPool<Foo> _pool = null!;
private Foo[][] _stores = null!;
private ManualResetEventSlim _terminate = null!;
private Task[] _tasks = null!;

[Params(8, 16, 64, 256, 1024, 2048)]
public int Count { get; set; }

[Params(1, 2, 4, 8)]
public int ThreadCount { get; set; }

[GlobalSetup]
public void GlobalSetup()
{
_pool = new DefaultObjectPool<Foo>(new DefaultPooledObjectPolicy<Foo>(), Count);
for (int i = 0; i < Count; i++)
{
_pool.Return(new Foo());
}

_stores = new Foo[ThreadCount][];
for (int i = 0; i < ThreadCount; i++)
{
_stores[i] = new Foo[Count];
}

_terminate = new ManualResetEventSlim();

_tasks = new Task[ThreadCount - 1];
for (int i = 0; i < ThreadCount - 1; i++)
{
int threadIndex = i;
_tasks[i] = Task.Run(() =>
{
while (!_terminate.IsSet)
{
BenchmarkLoop(_stores[threadIndex]);
}
});
}

// give ample time to the contention tasks to start running
Thread.Sleep(250);
}

[GlobalCleanup]
public void GlobalCleanup()
{
_terminate.Set();
Task.WaitAll(_tasks);
_terminate.Dispose();
}

[Benchmark]
public void DrainRefillMulti()
{
BenchmarkLoop(_stores[ThreadCount - 1]); // take the last slot
}

private void BenchmarkLoop(Foo[] store)
{
int num = (Count / ThreadCount) - 1;

for (int i = 0; i < num; i++)
{
store[i] = _pool.Get();
store[i].SimulateWork();
}

for (int i = 0; i < num; i++)
{
store[i].SimulateWork();
_pool.Return(store[i]);
}
}
}
44 changes: 44 additions & 0 deletions src/ObjectPool/perf/Microbenchmarks/DrainRefillSingleThreaded.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using BenchmarkDotNet.Attributes;

namespace Microsoft.Extensions.ObjectPool.Microbenchmarks;

#pragma warning disable R9A038, S109

[MemoryDiagnoser]
public class DrainRefillSingleThreaded
{
private DefaultObjectPool<Foo> _pool = null!;
private Foo[] _store = null!;

[Params(8, 16, 64, 256, 1024, 2048)]
public int Count { get; set; }

[GlobalSetup]
public void GlobalSetup()
{
_pool = new DefaultObjectPool<Foo>(new DefaultPooledObjectPolicy<Foo>(), Count);
for (int i = 0; i < Count; i++)
{
_pool.Return(new Foo());
}

_store = new Foo[Count];
}

[Benchmark]
public void DrainRefillSingle()
{
for (int i = 0; i < Count; i++)
{
_store[i] = _pool.Get();
}

for (int i = 0; i < Count; i++)
{
_pool.Return(_store[i]);
}
}
}
22 changes: 22 additions & 0 deletions src/ObjectPool/perf/Microbenchmarks/Foo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Microsoft.Extensions.ObjectPool.Microbenchmarks;

#pragma warning disable S109, CPR138

internal sealed class Foo
{
public int LastRandom;

public void SimulateWork()
{
// burn some cycles to simulate work being done between get and return
for (int i = 0; i <= 32; i++)
{
LastRandom = Random.Shared.Next();
}
}
}
72 changes: 72 additions & 0 deletions src/ObjectPool/perf/Microbenchmarks/GetReturnMultiThreaded.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;

namespace Microsoft.Extensions.ObjectPool.Microbenchmarks;

[MemoryDiagnoser]
public class GetReturnMultiThreaded
{
private const int Count = 8;

private DefaultObjectPool<Foo> _pool = null!;
private ManualResetEventSlim _terminate = null!;
private Task[] _tasks = null!;

[Params(1, 2, 4, 8)]
public int ThreadCount { get; set; }

[GlobalSetup]
public void GlobalSetup()
{
_pool = new DefaultObjectPool<Foo>(new DefaultPooledObjectPolicy<Foo>(), Count);
for (int i = 0; i < Count; i++)
{
_pool.Return(new Foo());
}

_terminate = new ManualResetEventSlim();

_tasks = new Task[ThreadCount - 1];
for (int i = 0; i < ThreadCount - 1; i++)
{
int threadIndex = i;
_tasks[i] = Task.Run(() =>
{
while (!_terminate.IsSet)
{
BenchmarkLoop();
}
});
}

// give ample time to the contention tasks to start running
Thread.Sleep(250);
}

[GlobalCleanup]
public void GlobalCleanup()
{
_terminate.Set();
Task.WaitAll(_tasks);
_terminate.Dispose();
}

[Benchmark]
public void GetReturnMulti()
{
BenchmarkLoop();
}

private void BenchmarkLoop()
{
var o = _pool.Get();

o.SimulateWork();

_pool.Return(o);
}
}
29 changes: 29 additions & 0 deletions src/ObjectPool/perf/Microbenchmarks/GetReturnSingleThreaded.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using BenchmarkDotNet.Attributes;

namespace Microsoft.Extensions.ObjectPool.Microbenchmarks;

[MemoryDiagnoser]
public class GetReturnSingleThreaded
{
private const int Count = 8;
private DefaultObjectPool<Foo> _pool = null!;

[GlobalSetup]
public void GlobalSetup()
{
_pool = new DefaultObjectPool<Foo>(new DefaultPooledObjectPolicy<Foo>(), Count);
for (int i = 0; i < Count; i++)
{
_pool.Return(new Foo());
}
}

[Benchmark]
public void GetReturnSingle()
{
_pool.Return(_pool.Get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
<ServerGarbageCollection>true</ServerGarbageCollection>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TieredCompilation>false</TieredCompilation>
<DefineConstants>$(DefineConstants);IS_BENCHMARKS</DefineConstants>
</PropertyGroup>

<ItemGroup>
<Reference Include="Microsoft.Extensions.ObjectPool" />
<Reference Include="BenchmarkDotNet" />
<Compile Include="$(SharedSourceRoot)BenchmarkRunner\*.cs" />
</ItemGroup>

</Project>
Loading