-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from cklutz/array-sampling
Array sampling, object pooling & more
- Loading branch information
Showing
23 changed files
with
2,103 additions
and
530 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
src/ManagedObjectSize.Benchmarks/ArraySamplingBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using BenchmarkDotNet.Diagnostics.Windows.Configs; | ||
|
||
namespace ManagedObjectSize.Benchmarks | ||
{ | ||
[MemoryDiagnoser, EtwProfiler] | ||
public class ArraySamplingBenchmarks | ||
{ | ||
[Params(20, 100)] public int N; | ||
|
||
private GraphObject m_graphData = null!; | ||
private int[] m_intData = null!; | ||
private string[] m_stringData = null!; | ||
|
||
private ObjectSizeOptions m_samplingOptions = null!; | ||
|
||
[GlobalSetup] | ||
public void GlobalSetup() | ||
{ | ||
m_graphData = GraphObject.CreateObjectGraph(N); | ||
m_intData = new int[N]; | ||
m_stringData = new string[N]; | ||
|
||
for (int i = 0; i < N; i++) | ||
{ | ||
m_intData[i] = i; | ||
m_stringData[i] = "string#" + i; | ||
} | ||
|
||
m_samplingOptions = new() { ArraySampleCount = N / 10 }; | ||
} | ||
|
||
[Benchmark] public long NoSampling_Int32() => ObjectSize.GetObjectInclusiveSize(m_intData); | ||
[Benchmark] public long NoSampling_String() => ObjectSize.GetObjectInclusiveSize(m_stringData); | ||
[Benchmark] public long NoSampling_Graph() => ObjectSize.GetObjectInclusiveSize(m_graphData); | ||
|
||
[Benchmark] public long Sampling_Int32() => ObjectSize.GetObjectInclusiveSize(m_intData, m_samplingOptions); | ||
[Benchmark] public long Sampling_String() => ObjectSize.GetObjectInclusiveSize(m_stringData, m_samplingOptions); | ||
[Benchmark] public long Sampling_Graph() => ObjectSize.GetObjectInclusiveSize(m_graphData, m_samplingOptions); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
namespace ManagedObjectSize.Benchmarks | ||
{ | ||
internal class GraphObject | ||
{ | ||
public static GraphObject CreateObjectGraph(int num, bool inner = false) | ||
{ | ||
var graph = new GraphObject | ||
{ | ||
ListField = new List<GraphNodeObject>(num) | ||
}; | ||
|
||
int digits = (int)Math.Log10(num) + 1; | ||
var options = new ParallelOptions { MaxDegreeOfParallelism = (inner || num < 100) ? 1 : Environment.ProcessorCount }; | ||
Parallel.For(0, num, options, | ||
() => new List<GraphNodeObject>(), | ||
(i, state, local) => | ||
{ | ||
var node = new GraphNodeObject { StringField = "Node#" }; | ||
if (!inner) | ||
{ | ||
node.ObjectField = CreateObjectGraph(100, true); | ||
} | ||
local.Add(node); | ||
return local; | ||
}, | ||
local => | ||
{ | ||
lock (graph.ListField) | ||
{ | ||
graph.ListField.AddRange(local); | ||
} | ||
}); | ||
|
||
return graph; | ||
} | ||
|
||
#pragma warning disable CS0649 | ||
|
||
public int IntField; | ||
public List<GraphNodeObject> ListField = null!; | ||
|
||
public class GraphNodeObject | ||
{ | ||
public double DoubleField; | ||
public int IntField; | ||
public string StringField = null!; | ||
public GraphObject ObjectField = null!; | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/ManagedObjectSize.Benchmarks/ManagedObjectSize.Benchmarks.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\ManagedObjectSize.ObjectPool\ManagedObjectSize.ObjectPool.csproj" /> | ||
<ProjectReference Include="..\ManagedObjectSize\ManagedObjectSize.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using ManagedObjectSize.ObjectPool; | ||
|
||
namespace ManagedObjectSize.Benchmarks | ||
{ | ||
[MemoryDiagnoser] | ||
public class ObjectPoolBenchmarks | ||
{ | ||
[Params(100, 1000)] public int N; | ||
|
||
private GraphObject m_graphData = null!; | ||
private ObjectSizeOptions m_options = null!; | ||
|
||
[GlobalSetup] | ||
public void GlobalSetup() | ||
{ | ||
m_graphData = GraphObject.CreateObjectGraph(N); | ||
m_options = new ObjectSizeOptions().UseMicrosoftExtensionsObjectPool(); | ||
} | ||
|
||
[Benchmark] public long NoPool() => ObjectSize.GetObjectInclusiveSize(m_graphData); | ||
|
||
[Benchmark] public long Pool() => ObjectSize.GetObjectInclusiveSize(m_graphData, m_options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using BenchmarkDotNet.Configs; | ||
using BenchmarkDotNet.Running; | ||
|
||
namespace ManagedObjectSize.Benchmarks | ||
{ | ||
internal class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
var xargs = new List<string>(args); | ||
var config = ManualConfig.Create(DefaultConfig.Instance); | ||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(xargs.ToArray(), config); | ||
} | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
src/ManagedObjectSize.ObjectPool/ManagedObjectSize.ObjectPool.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
|
||
<IsPackable>true</IsPackable> | ||
<PackageId>ManagedObjectSize.ObjectPool</PackageId> | ||
<Version>0.0.6</Version> | ||
<Authors>Christian Klutz</Authors> | ||
<Description> | ||
Adapts Microsoft.Extensions.ObjectPool to be used with ManagedObjectSize package. | ||
</Description> | ||
<InformationalVersion>$(Version).0</InformationalVersion> | ||
<FileVersion>$(Version).0</FileVersion> | ||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile> | ||
<RepositoryUrl>https://github.com/cklutz/ManagedObjectSize</RepositoryUrl> | ||
<RepositoryType>git</RepositoryType> | ||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Include="..\..\LICENSE.txt" Link="LICENSE.txt"> | ||
<PackagePath>\</PackagePath> | ||
<Pack>true</Pack> | ||
</None> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\ManagedObjectSize\ManagedObjectSize.csproj" /> | ||
</ItemGroup> | ||
|
||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" /> | ||
</ItemGroup> | ||
|
||
</Project> |
45 changes: 45 additions & 0 deletions
45
src/ManagedObjectSize.ObjectPool/MicrosoftExtensionsObjectPoolPoolProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using ManagedObjectSize.Pooling; | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace ManagedObjectSize.ObjectPool | ||
{ | ||
/// <summary> | ||
/// Adapts a <see cref="Microsoft.Extensions.ObjectPool.ObjectPool"/> to be used | ||
/// as <see cref="ObjectSizeOptions.PoolProvider"/>. | ||
/// </summary> | ||
public class MicrosoftExtensionsObjectPoolPoolProvider : PoolProvider | ||
{ | ||
private class PolicyAdapter<T> : IPooledObjectPolicy<T> where T : notnull | ||
{ | ||
private readonly IPoolPolicy<T> m_policy; | ||
public PolicyAdapter(IPoolPolicy<T> policy) => m_policy = policy; | ||
public T Create() => m_policy.Create(); | ||
public bool Return(T obj) => m_policy.Return(obj); | ||
} | ||
|
||
private class PoolAdapter<T> : Pool<T> where T : class | ||
{ | ||
private readonly ObjectPool<T> m_pool; | ||
public PoolAdapter(ObjectPool<T> pool) => m_pool = pool; | ||
public override T Get() => m_pool.Get(); | ||
public override void Return(T obj) => m_pool.Return(obj); | ||
} | ||
|
||
private readonly ObjectPoolProvider m_provider; | ||
|
||
public MicrosoftExtensionsObjectPoolPoolProvider() | ||
: this(new DefaultObjectPoolProvider()) | ||
{ | ||
} | ||
|
||
public MicrosoftExtensionsObjectPoolPoolProvider(ObjectPoolProvider objectPoolProvider) | ||
{ | ||
m_provider = objectPoolProvider ?? throw new ArgumentNullException(nameof(objectPoolProvider)); | ||
} | ||
|
||
public override Pool<T> Create<T>(IPoolPolicy<T> policy) | ||
{ | ||
return new PoolAdapter<T>(m_provider.Create(new PolicyAdapter<T>(policy))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace ManagedObjectSize.ObjectPool | ||
{ | ||
public static class ObjectPoolExtensions | ||
{ | ||
/// <summary> | ||
/// Configures <see cref="ObjectSizeOptions"/> to use an object pool based on <see cref="ObjectPoolProvider"/>. | ||
/// </summary> | ||
/// <param name="options">The options instance.</param> | ||
/// <param name="provider"> | ||
/// The <see cref="ObjectPoolProvider"/> to be used. If <c>null</c>, an instance of the <see cref="DefaultObjectPoolProvider"/> will be used.</param> | ||
/// <returns>The options instanced given as <paramref name="options"/>.</returns> | ||
public static ObjectSizeOptions UseMicrosoftExtensionsObjectPool(this ObjectSizeOptions options, ObjectPoolProvider? provider = null) | ||
{ | ||
if (provider == null) | ||
{ | ||
options.PoolProvider = new MicrosoftExtensionsObjectPoolPoolProvider(); | ||
} | ||
else | ||
{ | ||
options.PoolProvider = new MicrosoftExtensionsObjectPoolPoolProvider(provider); | ||
} | ||
|
||
return options; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
|
||
namespace ManagedObjectSize.Tests | ||
{ | ||
[TestClass] | ||
public class ObjectSizeOptionsTests | ||
{ | ||
[DataTestMethod] | ||
[DataRow(0.95, 5, 100, 80)] | ||
[DataRow(0.99, 5, 100, 87)] | ||
[DataRow(0.95, 5, 100_000_000, 384)] | ||
[DataRow(0.99, 5, 100_000_000, 663)] | ||
public void CalculateSampleCount(double confidenceLevel, int confidenceInterval, int populationSize, int expectedSampleSize) | ||
{ | ||
int actualSampleSize = Utils.CalculateSampleCount(confidenceLevel, confidenceInterval, populationSize); | ||
Assert.AreEqual(expectedSampleSize, actualSampleSize); | ||
} | ||
} | ||
} |
Oops, something went wrong.