Object Pool Benchmark Results
Date Added (UTC):
21 May 2024 @ 18:25
Date Updated (UTC):21 May 2024 @ 18:25
.NET Version(s): Tag(s):
#.Net8PerfImprovement #DBOperations #FileIO #ObjectMapping #StringBuilder
Added By:
A dedicated executive technical architect who is focused on expanding organizations technology capabilities.
Benchmark Results:
Benchmark Code:
https://gist.github.com/admir-live/db304653649bd55f5f4eebba3d29d537
The original benchmark may have changed.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.ObjectPool;
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
[MemoryDiagnoser]
public class ObjectPoolBenchmarks
{
private ObjectPool<ReusableBuffer> _bufferPool;
private readonly string _sampleText = "The Test Text...";
[GlobalSetup]
public void Setup()
{
var services = new ServiceCollection();
services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
services.AddSingleton<ObjectPool<ReusableBuffer>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new DefaultPooledObjectPolicy<ReusableBuffer>();
return provider.Create(policy);
});
var serviceProvider = services.BuildServiceProvider();
_bufferPool = serviceProvider.GetRequiredService<ObjectPool<ReusableBuffer>>();
}
[Benchmark]
public string ComputeHashWithoutPooling()
{
var buffer = new byte[1024 * 1024]; // 1 MB
for (var i = 0; i < _sampleText.Length; i++)
{
buffer[i] = (byte)_sampleText[i];
}
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(buffer.AsSpan(0, _sampleText.Length), hash);
return Convert.ToHexString(hash);
}
[Benchmark]
public string ComputeHashWithPooling()
{
var buffer = _bufferPool.Get();
try
{
for (var i = 0; i < _sampleText.Length; i++)
{
buffer.Data[i] = (byte)_sampleText[i];
}
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(buffer.Data.AsSpan(0, _sampleText.Length), hash);
return Convert.ToHexString(hash);
}
finally
{
_bufferPool.Return(buffer);
}
}
}
public class ReusableBuffer : IResettable
{
public byte[] Data { get; } = new byte[1024 * 1024];
public bool TryReset()
{
Array.Clear(Data);
return true;
}
}
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<ObjectPoolBenchmarks>();
}
}
// .NET 8 Lowered C# Code unavailable due to errors:
error CS0234: The type or namespace name 'ObjectPool' does not exist in the namespace 'Microsoft.Extensions' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'IResettable' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'ObjectPool<>' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'ObjectPoolProvider' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DefaultObjectPoolProvider' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DefaultPooledObjectPolicy<>' could not be found (are you missing a using directive or an assembly reference?)
error CS1061: 'ServiceCollection' does not contain a definition for 'BuildServiceProvider' and no accessible extension method 'BuildServiceProvider' accepting a first argument of type 'ServiceCollection' could be found (are you missing a using directive or an assembly reference?)
// .NET 8 IL Code unavailable due to errors:
error CS0234: The type or namespace name 'ObjectPool' does not exist in the namespace 'Microsoft.Extensions' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'ObjectPool<>' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'IResettable' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'ObjectPoolProvider' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DefaultObjectPoolProvider' could not be found (are you missing a using directive or an assembly reference?)
error CS0246: The type or namespace name 'DefaultPooledObjectPolicy<>' could not be found (are you missing a using directive or an assembly reference?)
error CS1061: 'ServiceCollection' does not contain a definition for 'BuildServiceProvider' and no accessible extension method 'BuildServiceProvider' accepting a first argument of type 'ServiceCollection' could be found (are you missing a using directive or an assembly reference?)
|
Benchmark Description:
Object Pool Benchmark Results
Overview
This benchmark compares the performance of computing SHA256 hashes with and without using an object pool for buffer reuse. The objective is to measure the time taken and memory allocated for each method.
Benchmark Setup
- Buffer Size: 1 MB
- Sample Text: "BenchmarkDotNetSampleText"
- Hash Algorithm: SHA256
- Object Pool:
ObjectPool<ReusableBuffer>
Methods
-
ComputeHashWithoutPooling:
- Allocates a new 1 MB buffer each time.
- Computes the SHA256 hash.
-
ComputeHashWithPooling:
- Uses an object pool to reuse a 1 MB buffer.
- Computes the SHA256 hash.
- Returns the buffer to the pool after use.
Key Takeaways
-
Performance:
- With Pooling: Faster (11.63 us)
- Without Pooling: Slower (21.51 us)
-
Memory Allocation:
- With Pooling: Significantly lower (152 B)
- Without Pooling: Much higher (1048862 B)
Conclusion
Using an object pool for buffer reuse greatly improves performance and reduces memory allocation. This is beneficial for scenarios where large buffers are frequently needed and can be reused, leading to more efficient resource utilization.