Created
September 21, 2019 16:30
-
-
Save xoofx/12f8013782ca9408864c9fb20131e6d7 to your computer and use it in GitHub Desktop.
Bench of GCHandle reused
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
// The following benchmark shows a barely known capability of GCHandle to be reused via their .Target | |
// as it is avoiding to reallocate an expensive entry into the GC table handle in the CLR runtime | |
/* | |
BenchmarkDotNet=v0.10.12, OS=Windows 10.0.18362 | |
AMD Ryzen 9 3900X 12-Core Processor, 1 CPU, 24 logical cores and 12 physical cores | |
.NET Core SDK=3.0.100-rc1-014190 | |
[Host] : .NET Core 2.1.13 (Framework 4.6.28008.01), 64bit RyuJIT | |
DefaultJob : .NET Core 2.1.13 (Framework 4.6.28008.01), 64bit RyuJIT | |
Method | Mean | Error | StdDev | Gen 0 | Allocated | | |
-------------------- |----------:|----------:|----------:|--------:|----------:| | |
TestGCHandle | 77.69 us | 0.5484 us | 0.5130 us | 14.4043 | 23.44 KB | | |
TestGCHandleReuse | 37.82 us | 0.6268 us | 0.5863 us | 14.4043 | 23.44 KB | | |
TestWeakReferencesT | 134.94 us | 1.0771 us | 1.0075 us | 28.8086 | 46.88 KB | | |
TestWeakReferences | 138.02 us | 0.7480 us | 0.6631 us | 28.8086 | 46.88 KB | | |
*/ | |
using System; | |
using System.Collections.Generic; | |
using System.Runtime.InteropServices; | |
using BenchmarkDotNet.Attributes; | |
namespace TestBenchmark | |
{ | |
[MemoryDiagnoser] | |
public class BenchGCHandleReused | |
{ | |
private readonly List<WeakReference<object>> _weakReferencesT; | |
private readonly GCHandle[] _gcHandles; | |
private readonly List<WeakReference> _weakReferences; | |
private const int Count = 1000; | |
public BenchWeakReferences() | |
{ | |
_weakReferencesT = new List<WeakReference<object>>(); | |
_gcHandles = new GCHandle[Count]; | |
_weakReferences = new List<WeakReference>(); | |
} | |
[Benchmark] | |
public int TestGCHandle() | |
{ | |
// Clear all GC handles | |
for (int i = 0; i < _gcHandles.Length; i++) | |
{ | |
ref var gcHandle = ref _gcHandles[i]; | |
if (gcHandle.IsAllocated) | |
{ | |
_gcHandles[i].Free(); | |
} | |
} | |
for (int i = 0; i < Count; i++) | |
{ | |
_gcHandles[i] = GCHandle.Alloc(new object(), GCHandleType.Weak); | |
} | |
int result = 0; | |
for (int i = 0; i < Count; i++) | |
{ | |
if (_gcHandles[i].Target != null) | |
{ | |
result++; | |
} | |
} | |
return result; | |
} | |
[Benchmark] | |
public int TestGCHandleReuse() | |
{ | |
// Clear all GC handles | |
for (int i = 0; i < _gcHandles.Length; i++) | |
{ | |
ref var gcHandle = ref _gcHandles[i]; | |
if (gcHandle.IsAllocated) | |
{ | |
_gcHandles[i].Target = null; | |
} | |
} | |
for (int i = 0; i < Count; i++) | |
{ | |
ref var gcHandle = ref _gcHandles[i]; | |
var obj = new object(); | |
if (gcHandle.IsAllocated) | |
{ | |
gcHandle.Target = obj; | |
} | |
else | |
{ | |
gcHandle = GCHandle.Alloc(obj, GCHandleType.Weak); | |
} | |
} | |
int result = 0; | |
for (int i = 0; i < Count; i++) | |
{ | |
if (_gcHandles[i].Target != null) | |
{ | |
result++; | |
} | |
} | |
return result; | |
} | |
[Benchmark] | |
public int TestWeakReferencesT() | |
{ | |
_weakReferencesT.Clear(); | |
for (int i = 0; i < Count; i++) | |
{ | |
_weakReferencesT.Add(new WeakReference<object>(new object())); | |
} | |
int result = 0; | |
for (int i = 0; i < Count; i++) | |
{ | |
object obj; | |
if (_weakReferencesT[i].TryGetTarget(out obj)) | |
{ | |
result++; | |
} | |
} | |
return result; | |
} | |
[Benchmark] | |
public int TestWeakReferences() | |
{ | |
_weakReferences.Clear(); | |
for (int i = 0; i < Count; i++) | |
{ | |
_weakReferences.Add(new WeakReference(new object())); | |
} | |
int result = 0; | |
for (int i = 0; i < Count; i++) | |
{ | |
if (_weakReferences[i].IsAlive) | |
{ | |
result++; | |
} | |
} | |
return result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment