Skip to content

Commit 2bc47a5

Browse files
authored
optimize sketch reset (#273)
* unroll * cleanup * rename * rename
1 parent 18dcd88 commit 2bc47a5

File tree

2 files changed

+101
-4
lines changed

2 files changed

+101
-4
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+

2+
using BenchmarkDotNet.Attributes;
3+
using BenchmarkDotNet.Jobs;
4+
5+
namespace BitFaster.Caching.Benchmarks.Lfu
6+
{
7+
[SimpleJob(RuntimeMoniker.Net60)]
8+
public class SketchReset
9+
{
10+
static long ResetMask = 0x7777777777777777L;
11+
static long OneMask = 0x1111111111111111L;
12+
13+
long[] table;
14+
15+
[Params(4, 128, 8192, 1048576)]
16+
public int Size { get; set; }
17+
18+
[GlobalSetup]
19+
public void Setup()
20+
{
21+
table = new long[Size];
22+
}
23+
24+
[Benchmark(Baseline = true)]
25+
public int Reset1()
26+
{
27+
int count = 0;
28+
for (int i = 0; i < table.Length; i++)
29+
{
30+
count += BitOps.BitCount(table[i] & OneMask);
31+
table[i] = (long)((ulong)table[i] >> 1) & ResetMask;
32+
}
33+
34+
return count;
35+
}
36+
37+
[Benchmark()]
38+
public int Reset2()
39+
{
40+
int count0 = 0;
41+
int count1 = 0;
42+
43+
for (int i = 0; i < table.Length; i += 2)
44+
{
45+
count0 += BitOps.BitCount(table[i] & OneMask);
46+
count1 += BitOps.BitCount(table[i + 1] & OneMask);
47+
48+
table[i] = (long)((ulong)table[i] >> 1) & ResetMask;
49+
table[i + 1] = (long)((ulong)table[i + 1] >> 1) & ResetMask;
50+
}
51+
52+
return count0 + count1;
53+
}
54+
55+
[Benchmark()]
56+
public int Reset4()
57+
{
58+
int count0 = 0;
59+
int count1 = 0;
60+
int count2 = 0;
61+
int count3 = 0;
62+
63+
for (int i = 0; i < table.Length; i += 4)
64+
{
65+
count0 += BitOps.BitCount(table[i] & OneMask);
66+
count1 += BitOps.BitCount(table[i + 1] & OneMask);
67+
count2 += BitOps.BitCount(table[i + 2] & OneMask);
68+
count3 += BitOps.BitCount(table[i + 3] & OneMask);
69+
70+
table[i] = (long)((ulong)table[i] >> 1) & ResetMask;
71+
table[i + 1] = (long)((ulong)table[i + 1] >> 1) & ResetMask;
72+
table[i + 2] = (long)((ulong)table[i + 2] >> 1) & ResetMask;
73+
table[i + 3] = (long)((ulong)table[i + 3] >> 1) & ResetMask;
74+
}
75+
76+
return (count0 + count1) + (count2 + count3);
77+
}
78+
}
79+
}

BitFaster.Caching/Lfu/CmSketch.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,37 @@ private bool IncrementAt(int i, int j)
158158

159159
private void Reset()
160160
{
161-
int count = 0;
162-
for (int i = 0; i < table.Length; i++)
161+
// unroll, almost 2x faster
162+
int count0 = 0;
163+
int count1 = 0;
164+
int count2 = 0;
165+
int count3 = 0;
166+
167+
for (int i = 0; i < table.Length; i += 4)
163168
{
164-
count += BitOps.BitCount(table[i] & OneMask);
169+
count0 += BitOps.BitCount(table[i] & OneMask);
170+
count1 += BitOps.BitCount(table[i + 1] & OneMask);
171+
count2 += BitOps.BitCount(table[i + 2] & OneMask);
172+
count3 += BitOps.BitCount(table[i + 3] & OneMask);
173+
165174
table[i] = (long)((ulong)table[i] >> 1) & ResetMask;
175+
table[i + 1] = (long)((ulong)table[i + 1] >> 1) & ResetMask;
176+
table[i + 2] = (long)((ulong)table[i + 2] >> 1) & ResetMask;
177+
table[i + 3] = (long)((ulong)table[i + 3] >> 1) & ResetMask;
166178
}
167-
size = (size - (count >> 2)) >> 1;
179+
180+
count0 = (count0 + count1) + (count2 + count3);
181+
182+
size = (size - (count0 >> 2)) >> 1;
168183
}
169184

170185
private void EnsureCapacity(long maximumSize)
171186
{
172187
int maximum = (int)Math.Min(maximumSize, int.MaxValue >> 1);
173188

189+
// clamp to 4 as min size
190+
maximum = Math.Max(4, maximum);
191+
174192
table = new long[(maximum == 0) ? 1 : BitOps.CeilingPowerOfTwo(maximum)];
175193
tableMask = Math.Max(0, table.Length - 1);
176194
sampleSize = (maximumSize == 0) ? 10 : (10 * maximum);

0 commit comments

Comments
 (0)