Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
var source = GenerateTestData(maxBit);

_testValues = source
.Skip(Math.Max(0, source.Count() - TEST_VALUE_LENGTH))

Check warning on line 42 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Use the "Length" property instead of Enumerable.Count() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1829)
.Select(d => d.Value)
.ToArray();

Expand All @@ -53,7 +53,6 @@
var functions = new Dictionary<string, Func<long, int>>
{
{"CurrentImpl", Bitwise.NumberOfLeadingZeros},
{"Imperative", Bitwise.Imperative.NumberOfLeadingZeros},
{"IfAndShift", LeadingZeroCount.IfAndShift.GetLeadingZeroCount},
//{"MathLog", LeadingZeroCount.MathLog.GetLeadingZeroCount},
{"StringManipulation", LeadingZeroCount.StringManipulation.GetLeadingZeroCount},
Expand Down Expand Up @@ -121,17 +120,6 @@
return sum;
}

[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int ImperativeImplementation()
{
var sum = 0;
for (int i = 0; i < _testValues.Length; i++)
{
sum += Bitwise.Imperative.NumberOfLeadingZeros(_testValues[i]);
}
return sum;
}

[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int IfAndShift()
{
Expand Down Expand Up @@ -198,7 +186,7 @@
return sum;
}
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int BBarry_imp1()

Check warning on line 189 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Remove the underscores from member name HdrHistogram.Benchmarking.LeadingZeroCount.LeadingZeroCountBenchmarkBase.BBarry_imp1() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
{
var sum = 0;
for (int i = 0; i < _testValues.Length; i++)
Expand All @@ -208,7 +196,7 @@
return sum;
}
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int BBarry_imp2()

Check warning on line 199 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Remove the underscores from member name HdrHistogram.Benchmarking.LeadingZeroCount.LeadingZeroCountBenchmarkBase.BBarry_imp2() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
{
var sum = 0;
for (int i = 0; i < _testValues.Length; i++)
Expand All @@ -218,7 +206,7 @@
return sum;
}
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int BBarry_imp3()

Check warning on line 209 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Remove the underscores from member name HdrHistogram.Benchmarking.LeadingZeroCount.LeadingZeroCountBenchmarkBase.BBarry_imp3() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
{
var sum = 0;
for (int i = 0; i < _testValues.Length; i++)
Expand All @@ -228,7 +216,7 @@
return sum;
}
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
public int BBarry_imp4()

Check warning on line 219 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Remove the underscores from member name HdrHistogram.Benchmarking.LeadingZeroCount.LeadingZeroCountBenchmarkBase.BBarry_imp4() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
{
var sum = 0;
for (int i = 0; i < _testValues.Length; i++)
Expand All @@ -239,7 +227,7 @@
}


private class CalculationExpectation

Check warning on line 230 in HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

View workflow job for this annotation

GitHub Actions / build

Type 'CalculationExpectation' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public long Value { get; }
public int Expected { get; }
Expand Down
45 changes: 45 additions & 0 deletions HdrHistogram.UnitTests/Utilities/BitwiseTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* This is a .NET port of the original Java version, which was written by
* Gil Tene as described in
* https://github.com/HdrHistogram/HdrHistogram
* and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/

using HdrHistogram.Utilities;
using Xunit;

namespace HdrHistogram.UnitTests.Utilities
{
public class BitwiseTests
{
[Theory]
[InlineData(0L, 64)]
[InlineData(1L, 63)]
[InlineData(2L, 62)]
[InlineData(4L, 61)]
[InlineData(8L, 60)]
[InlineData(16L, 59)]
[InlineData(32L, 58)]
[InlineData(64L, 57)]
[InlineData(128L, 56)]
[InlineData(256L, 55)]
[InlineData(512L, 54)]
[InlineData(1024L, 53)]
[InlineData(2048L, 52)]
[InlineData(4096L, 51)]
[InlineData(8192L, 50)]
[InlineData(16384L, 49)]
[InlineData(32768L, 48)]
[InlineData(65536L, 47)]
[InlineData(1L << 30, 33)]
[InlineData(1L << 31, 32)]
[InlineData(1L << 32, 31)]
[InlineData(1L << 62, 1)]
[InlineData(long.MaxValue, 1)]
public void NumberOfLeadingZeros_ReturnsCorrectValue(long value, int expected)
{
Assert.Equal(expected, Bitwise.NumberOfLeadingZeros(value));
}
}
}
23 changes: 5 additions & 18 deletions HdrHistogram/HdrHistogram.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
<Description>HdrHistogram supports low latency recording and analyzing of sampled data value counts across a configurable integer value range with configurable value precision within the range.</Description>
<Authors>Gil Tene, Lee Campbell</Authors>
<PackageReleaseNotes>Net 8.0 release</PackageReleaseNotes>
Expand All @@ -21,21 +21,8 @@
<None Include="../README.md" Pack="true" PackagePath="" />
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
<DocumentationFile>bin\Release\net8.0\HdrHistogram.xml</DocumentationFile>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DocumentationFile>bin\Release\$(TargetFramework)\HdrHistogram.xml</DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0|AnyCPU'">
<DocumentationFile>bin\Release\net9.0\HdrHistogram.xml</DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net10.0|AnyCPU'">
<DocumentationFile>bin\Release\net10.0\HdrHistogram.xml</DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
<DocumentationFile>bin\Release\netstandard2.0\HdrHistogram.xml</DocumentationFile>
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>

</Project>
</Project>
4 changes: 0 additions & 4 deletions HdrHistogram/HistogramLogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,7 @@ private IEnumerable<string> ReadLines()

private static bool IsComment(string line)
{
#if NETSTANDARD2_0
return line.StartsWith("#", StringComparison.Ordinal);
#else
return line.StartsWith('#');
#endif
}

private static bool IsStartTime(string line)
Expand Down
85 changes: 1 addition & 84 deletions HdrHistogram/Utilities/Bitwise.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,90 +22,7 @@ public static class Bitwise
/// <returns>The number of leading zeros.</returns>
public static int NumberOfLeadingZeros(long value)
{
#if NET5_0_OR_GREATER
return IntrinsicNumberOfLeadingZeros(value);
#else
return Imperative.NumberOfLeadingZeros(value);
#endif
}

#if NET5_0_OR_GREATER
/// <summary>
/// Returns the Leading Zero Count (lzc) of the <paramref name="value"/> for its binary representation.
/// </summary>
/// <param name="value">The value to find the number of leading zeros</param>
/// <returns>The number of leading zeros.</returns>
private static int IntrinsicNumberOfLeadingZeros(long value)
{
ulong testValue = (ulong)value;
return System.Numerics.BitOperations.LeadingZeroCount(testValue);

}
#endif

//Code has been tested and taken from :
//http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537
//http://stackoverflow.com/questions/21888140/de-bruijn-algorithm-binary-digit-count-64bits-c-sharp/21888542#21888542
//http://stackoverflow.com/questions/15967240/fastest-implementation-of-log2int-and-log2float
//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious

/// <summary>
/// Imperative implementation of the LeadingZeroCount, when access to the <c>System.Numerics.BitOperations.LeadingZeroCount(ulong)</c> is not available.
/// </summary>
public static class Imperative
{
private static readonly int[] Lookup;

static Imperative()
{
Lookup = new int[256];
for (int i = 1; i < 256; ++i)
{
Lookup[i] = (int)(Math.Log(i) / Math.Log(2));
}
}

/// <summary>
/// Returns the Leading Zero Count (lzc) of the <paramref name="value"/> for its binary representation.
/// </summary>
/// <param name="value">The value to find the number of leading zeros</param>
/// <returns>The number of leading zeros.</returns>
public static int NumberOfLeadingZeros(long value)
{
//Optimisation for 32 bit values. So values under 00:16:41.0 when measuring with Stopwatch.GetTimestamp()*, we will hit a fast path.
// * as at writing on Win10 .NET 4.6
if (value < int.MaxValue)
return 63 - Log2((int)value);
return NumberOfLeadingZerosLong(value);
}

private static int NumberOfLeadingZerosLong(long value)
{
// Code from http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537

//--Already checked that values here are over int.MaxValue, i.e. !=0
// HD, Figure 5-6
//if (value == 0)
// return 64;
var n = 1;
// >>> in Java is a "unsigned bit shift", to do the same in C# we use >> (but it HAS to be an unsigned int)
var x = (uint)(value >> 32);
if (x == 0) { n += 32; x = (uint)value; }
if (x >> 16 == 0) { n += 16; x <<= 16; }
if (x >> 24 == 0) { n += 8; x <<= 8; }
if (x >> 28 == 0) { n += 4; x <<= 4; }
if (x >> 30 == 0) { n += 2; x <<= 2; }
n -= (int)(x >> 31);
return n;
}

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];
}
return System.Numerics.BitOperations.LeadingZeroCount((ulong)value);
}
}
}
3 changes: 1 addition & 2 deletions spec/tech-standards/build-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ HdrHistogram.sln
### Main Library (HdrHistogram.csproj)

```xml
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
```

| Target | Description |
|--------|-------------|
| `net10.0` | Modern .NET (current LTS target) |
| `net9.0` | Modern .NET (STS target) |
| `net8.0` | Modern .NET (LTS target) |
| `netstandard2.0` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) |

### Test Project

Expand Down
Loading