Skip to content

Commit 73e400a

Browse files
committed
Adds conditional weak table benchmarks
1 parent fa3ec92 commit 73e400a

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

ModernUOBenchmarks.sln

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SortedSetVPriorityQueue", "
4949
EndProject
5050
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NPCPathing", "Benchmarks\NPCPathing\NPCPathing.csproj", "{EF3CC62F-781F-4AF4-9691-9C3F0D7311F8}"
5151
EndProject
52+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WeakTable", "WeakTable\WeakTable.csproj", "{57F7FC04-31B4-4254-9570-5CCBD645BD1F}"
53+
EndProject
5254
Global
5355
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5456
Debug|Any CPU = Debug|Any CPU
@@ -241,6 +243,14 @@ Global
241243
{EF3CC62F-781F-4AF4-9691-9C3F0D7311F8}.Release|Any CPU.Build.0 = Release|x64
242244
{EF3CC62F-781F-4AF4-9691-9C3F0D7311F8}.Release|x64.ActiveCfg = Release|x64
243245
{EF3CC62F-781F-4AF4-9691-9C3F0D7311F8}.Release|x64.Build.0 = Release|x64
246+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Debug|Any CPU.ActiveCfg = Debug|x64
247+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Debug|Any CPU.Build.0 = Debug|x64
248+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Debug|x64.ActiveCfg = Debug|x64
249+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Debug|x64.Build.0 = Debug|x64
250+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Release|Any CPU.ActiveCfg = Release|x64
251+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Release|Any CPU.Build.0 = Release|x64
252+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Release|x64.ActiveCfg = Release|x64
253+
{57F7FC04-31B4-4254-9570-5CCBD645BD1F}.Release|x64.Build.0 = Release|x64
244254
EndGlobalSection
245255
GlobalSection(SolutionProperties) = preSolution
246256
HideSolutionNode = FALSE
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using System;
2+
using BenchmarkDotNet.Attributes;
3+
using BenchmarkDotNet.Order;
4+
using System.Collections.Generic;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
7+
using BenchmarkDotNet.Jobs;
8+
9+
public class ObjectForCWT
10+
{
11+
// Other data to make the object somewhat realistic
12+
public long DataField1;
13+
public string DataField2;
14+
}
15+
16+
public class StateMachine
17+
{
18+
public long TimeDebt;
19+
public long LastDecayTime;
20+
public long LastMovementTime;
21+
}
22+
23+
public class ObjectWithDirectProperties
24+
{
25+
// Other data
26+
public long DataField1;
27+
public string DataField2;
28+
29+
// State machine properties
30+
public long TimeDebt;
31+
public long LastDecayTime;
32+
public long LastMovementTime;
33+
}
34+
35+
[SimpleJob(RuntimeMoniker.Net10_0)]
36+
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
37+
public class BenchmarkConditionalWeakTable
38+
{
39+
private static readonly ConditionalWeakTable<ObjectForCWT, StateMachine> _cwt = new();
40+
private List<ObjectForCWT> _cwtObjects;
41+
private List<ObjectWithDirectProperties> _directObjects;
42+
43+
[Params(10, 100, 1000)]
44+
public int N;
45+
46+
[GlobalSetup]
47+
public void Setup()
48+
{
49+
_cwtObjects = new List<ObjectForCWT>(N);
50+
_directObjects = new List<ObjectWithDirectProperties>(N);
51+
52+
for (int i = 0; i < N; i++)
53+
{
54+
var cwtObj = new ObjectForCWT { DataField1 = i, DataField2 = $"Object {i}" };
55+
var state = new StateMachine { TimeDebt = i, LastDecayTime = i - N, LastMovementTime = i * -N };
56+
57+
_cwtObjects.Add(cwtObj);
58+
_cwt.Add(cwtObj, state);
59+
60+
_directObjects.Add(new ObjectWithDirectProperties
61+
{
62+
DataField1 = i,
63+
DataField2 = $"Object {i}",
64+
TimeDebt = i,
65+
LastDecayTime = i - N,
66+
LastMovementTime = i * -N
67+
});
68+
}
69+
}
70+
71+
[Benchmark]
72+
public void ConditionalWeakTable_Access()
73+
{
74+
long totalState = 0;
75+
var span = CollectionsMarshal.AsSpan(_cwtObjects);
76+
for (var i = 0; i < span.Length; i++)
77+
{
78+
var obj = span[i];
79+
// The core operation: TryGetValue
80+
if (_cwt.TryGetValue(obj, out var state))
81+
{
82+
// Perform a simple read/write
83+
totalState += state!.TimeDebt++;
84+
}
85+
}
86+
87+
// Use the result to prevent dead code elimination
88+
if (totalState == -1) throw new Exception();
89+
}
90+
91+
[Benchmark(Baseline = true)]
92+
public void DirectProperty_Access()
93+
{
94+
long totalState = 0;
95+
var span = CollectionsMarshal.AsSpan(_directObjects);
96+
for (var i = 0; i < span.Length; i++)
97+
{
98+
var obj = span[i];
99+
// The core operation: direct access
100+
totalState += obj.TimeDebt++;
101+
}
102+
103+
// Use the result to prevent dead code elimination
104+
if (totalState == -1) throw new Exception();
105+
}
106+
}

WeakTable/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using BenchmarkDotNet.Running;
2+
3+
var benchmarks = BenchmarkRunner.Run<BenchmarkConditionalWeakTable>();

WeakTable/WeakTable.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>

0 commit comments

Comments
 (0)