Skip to content
Merged
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions BitFaster.Caching/Lfu/CmSketchCore.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


#if !NETSTANDARD2_0
Expand All @@ -24,14 +26,17 @@ namespace BitFaster.Caching.Lfu
/// </remarks>
/// This is a direct C# translation of FrequencySketch in the Caffeine library by [email protected] (Ben Manes).
/// https://github.com/ben-manes/caffeine
public class CmSketchCore<T, I>
public unsafe class CmSketchCore<T, I>
where T : notnull
where I : struct, IsaProbe
{
private const long ResetMask = 0x7777777777777777L;
private const long OneMask = 0x1111111111111111L;

private long[] table;
#if NET6_0_OR_GREATER
private long* tableAddr;
#endif
private int sampleSize;
private int blockMask;
private int size;
Expand Down Expand Up @@ -111,7 +116,7 @@ public void Increment(T value)
/// </summary>
public void Clear()
{
table = new long[table.Length];
Array.Clear(table, 0, table.Length);
size = 0;
}

Expand All @@ -120,8 +125,20 @@ private void EnsureCapacity(long maximumSize)
{
int maximum = (int)Math.Min(maximumSize, int.MaxValue >> 1);

#if NET6_0_OR_GREATER
// over alloc by 4 to give 32 bytes padding, tableAddr is then aligned to 32 bytes
const int pad = 4;
table = GC.AllocateArray<long>(Math.Max(BitOps.CeilingPowerOfTwo(maximum), 8) + pad, true);

tableAddr = (long*)Unsafe.AsPointer(ref table[0]);
tableAddr = (long*)((long)tableAddr + (long)tableAddr % 32);

blockMask = (int)((uint)(table.Length - pad) >> 3) - 1;

#else
table = new long[Math.Max(BitOps.CeilingPowerOfTwo(maximum), 8)];
blockMask = (int)((uint)table.Length >> 3) - 1;
blockMask = (int)((uint)(table.Length) >> 3) - 1;
#endif
sampleSize = (maximumSize == 0) ? 10 : (10 * maximum);

size = 0;
Expand Down Expand Up @@ -246,7 +263,11 @@ private unsafe int EstimateFrequencyAvx(T value)
Vector128<int> blockOffset = Avx2.Add(Vector128.Create(block), offset); // i - table index
blockOffset = Avx2.Add(blockOffset, Vector128.Create(0, 2, 4, 6)); // + (i << 1)

#if NET6_0_OR_GREATER
long* tablePtr = tableAddr;
#else
fixed (long* tablePtr = table)
#endif
{
Vector256<long> tableVector = Avx2.GatherVector256(tablePtr, blockOffset, 8);
index = Avx2.ShiftLeftLogical(index, 2);
Expand All @@ -264,7 +285,7 @@ private unsafe int EstimateFrequencyAvx(T value)
.AsUInt16();

// set the zeroed high parts of the long value to ushort.Max
#if NET6_0
#if NET6_0_OR_GREATER
count = Avx2.Blend(count, Vector128<ushort>.AllBitsSet, 0b10101010);
#else
count = Avx2.Blend(count, Vector128.Create(ushort.MaxValue), 0b10101010);
Expand All @@ -289,7 +310,11 @@ private unsafe void IncrementAvx(T value)
Vector128<int> blockOffset = Avx2.Add(Vector128.Create(block), offset); // i - table index
blockOffset = Avx2.Add(blockOffset, Vector128.Create(0, 2, 4, 6)); // + (i << 1)

#if NET6_0_OR_GREATER
long* tablePtr = tableAddr;
#else
fixed (long* tablePtr = table)
#endif
{
Vector256<long> tableVector = Avx2.GatherVector256(tablePtr, blockOffset, 8);

Expand Down