-
Notifications
You must be signed in to change notification settings - Fork 30
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 #60 from LeeCampbell/LeadingZeroCountBenchmark
Leading zero count benchmark
- Loading branch information
Showing
5 changed files
with
214 additions
and
10 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
109 changes: 109 additions & 0 deletions
109
HdrHistogram.Benchmarking/LeadingZeroCount/BBarry32BitIfShiftLookupWith64BitShiftBranch.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,109 @@ | ||
using System; | ||
|
||
namespace HdrHistogram.Benchmarking.LeadingZeroCount | ||
{ | ||
/// <summary> | ||
/// Contributed from @BBarry at https://github.com/HdrHistogram/HdrHistogram.NET/issues/42 | ||
/// This variation perfoms very well. Similar profile to the "Current Impl". | ||
/// Faster on LegacyJIT/CLR, but much slower on RyuJIT (CLR & Core) | ||
/// </summary> | ||
public static class BBarry32BitIfShiftLookupWith64BitShiftBranch | ||
{ | ||
private static readonly int[] Lookup; | ||
|
||
static BBarry32BitIfShiftLookupWith64BitShiftBranch() | ||
{ | ||
Lookup = new int[256]; | ||
for (int i = 1; i < 256; ++i) | ||
{ | ||
Lookup[i] = (int)(Math.Log(i) / Math.Log(2)); | ||
} | ||
} | ||
public static int GetLeadingZeroCount(long value) | ||
{ | ||
//TODO: Test this with just < instead of <=? i.e. const of int.Max+1; | ||
if (value <= int.MaxValue) | ||
return 63 - Log2((int)value); | ||
if (value <= uint.MaxValue) | ||
return 62 - Log2((int)(value >> 1)); | ||
return 31 - Log2((int)(value >> 32)); | ||
} | ||
|
||
private static int Log2(int i) | ||
{ | ||
if (i >= 0x1000000) { return Lookup[i >> 24] + 24; } | ||
if (i >= 0x10000) { return Lookup[i >> 16] + 16; } | ||
if (i >= 0x100) { return Lookup[i >> 8] + 8; } | ||
return Lookup[i]; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Contributed from @BBarry at https://github.com/HdrHistogram/HdrHistogram.NET/issues/42 | ||
/// This variation perfoms very well. Similar profile to the "Current Impl". | ||
/// Faster on LegacyJIT/CLR, but much slower on RyuJIT (CLR & Core) | ||
/// </summary> | ||
public static class BBarry32BitIfShiftLookupWith64BitShiftBranch_2 | ||
{ | ||
private static readonly int[] Lookup; | ||
static BBarry32BitIfShiftLookupWith64BitShiftBranch_2() | ||
{ | ||
Lookup = new int[256]; | ||
for (int i = 1; i < 256; ++i) | ||
{ | ||
Lookup[i] = (int)(Math.Log(i) / Math.Log(2)); | ||
} | ||
} | ||
public static int GetLeadingZeroCount(long value) | ||
{ | ||
if (value <= int.MaxValue) | ||
return 63 - Log2((uint)value); | ||
return 32 - Log2((uint)(value >> 31)); | ||
} | ||
|
||
private static int Log2(uint i) | ||
{ | ||
if (i >= 0x1000000) { return Lookup[i >> 24] + 24; } | ||
if (i >= 0x10000) { return Lookup[i >> 16] + 16; } | ||
if (i >= 0x100) { return Lookup[i >> 8] + 8; } | ||
return Lookup[i]; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Contributed from @BBarry at https://github.com/HdrHistogram/HdrHistogram.NET/issues/42 | ||
/// This variation perfoms very well. Similar profile to the "Current Impl". | ||
/// Faster on LegacyJIT/CLR, but much slower on RyuJIT (CLR & Core) | ||
/// This just compares only lessThan operator instead of lessThanEqualTo. #completeness | ||
/// </summary> | ||
public static class BBarry32BitIfShiftLookupWith64BitShiftBranch_3 | ||
{ | ||
private static readonly int[] Lookup; | ||
private const long IntOverflow = int.MaxValue + 1L; | ||
static BBarry32BitIfShiftLookupWith64BitShiftBranch_3() | ||
{ | ||
Lookup = new int[256]; | ||
for (int i = 1; i < 256; ++i) | ||
{ | ||
Lookup[i] = (int)(Math.Log(i) / Math.Log(2)); | ||
} | ||
} | ||
public static int GetLeadingZeroCount(long value) | ||
{ | ||
if (value < IntOverflow) | ||
return 63 - Log2((uint)value); | ||
return 32 - Log2((uint)(value >> 31)); | ||
} | ||
|
||
private const int Bit24Range = 0x1000000 - 1; | ||
private const int Bit16Range = 0x10000 - 1; | ||
private const int Bit8Range = 0x100 - 1; | ||
private static int Log2(uint i) | ||
{ | ||
if (i > Bit24Range) { return Lookup[i >> 24] + 24; } | ||
if (i > Bit16Range) { return Lookup[i >> 16] + 16; } | ||
if (i > Bit8Range) { return Lookup[i >> 8] + 8; } | ||
return Lookup[i]; | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
HdrHistogram.Benchmarking/LeadingZeroCount/BBarryIfShiftLookup.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,36 @@ | ||
using System; | ||
|
||
namespace HdrHistogram.Benchmarking.LeadingZeroCount | ||
{ | ||
/// <summary> | ||
/// Contributed from @BBarry at https://github.com/HdrHistogram/HdrHistogram.NET/issues/42 | ||
/// This variation inlines all the shifts. | ||
/// It performs on par on LegacyJIT/CLR but significantly slower on RyuJIT. | ||
/// I assume it is because 7 branches vs the 4 above. | ||
/// </summary> | ||
internal static class BBarryIfShiftLookup | ||
{ | ||
private static readonly int[] Lookup; | ||
|
||
static BBarryIfShiftLookup() | ||
{ | ||
Lookup = new int[256]; | ||
for (int i = 1; i < 256; ++i) | ||
{ | ||
Lookup[i] = (int)(Math.Log(i) / Math.Log(2)); | ||
} | ||
} | ||
|
||
public static int GetLeadingZeroCount(long value) | ||
{ | ||
if (value >= 0x100000000000000) { return 7 - Lookup[value >> 56]; } | ||
if (value >= 0x1000000000000) { return 15 - Lookup[value >> 48]; } | ||
if (value >= 0x10000000000) { return 23 - Lookup[value >> 40]; } | ||
if (value >= 0x100000000) { return 31 - Lookup[value >> 32]; } | ||
if (value >= 0x1000000) { return 39 - Lookup[value >> 24]; } | ||
if (value >= 0x10000) { return 47 - Lookup[value >> 16]; } | ||
if (value >= 0x100) { return 55 - Lookup[value >> 8]; } | ||
return 63 - Lookup[value]; | ||
} | ||
} | ||
} |
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