Skip to content

Commit 4ab3b16

Browse files
committed
feat: use 64 bytes as threshold
1 parent a2e7da3 commit 4ab3b16

File tree

4 files changed

+62
-32
lines changed

4 files changed

+62
-32
lines changed

src/Base58Encoding.Benchmarks/CountLeadingZerosBenchmark.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace Base58Encoding.Benchmarks;
1212
[SimpleJob(RuntimeMoniker.Net90)]
1313
[SimpleJob(RuntimeMoniker.Net10_0)]
1414
[HideColumns("Job", "Error", "StdDev", "Median", "RatioSD")]
15+
[DisassemblyDiagnoser]
1516
public class CountLeadingZerosBenchmark
1617
{
1718
private static Lazy<byte[][]> _lazyTestData = new(() =>
@@ -93,7 +94,7 @@ public int SimdOnly()
9394
return totalCount;
9495
}
9596

96-
[Benchmark(Baseline = true, Description = "Combined (Current)")]
97+
[Benchmark(Baseline = true, Description = "Combined (Current) - 16bytes SIMD threshold")]
9798
public int Combined()
9899
{
99100
int totalCount = 0;
@@ -209,11 +210,7 @@ private static int CountLeadingZerosSimdImpl(ReadOnlySpan<byte> data, out int pr
209210
[MethodImpl(MethodImplOptions.AggressiveInlining)]
210211
private static int CountLeadingZerosCombinedImpl(ReadOnlySpan<byte> data)
211212
{
212-
// intentionally commenting out, since other methods won't have it also
213-
//if (data.Length == 0)
214-
// return 0;
215-
216-
if (data.Length < 16)
213+
if (data.Length < 64)
217214
return CountLeadingZerosScalarImpl(data);
218215

219216
int count = CountLeadingZerosSimdImpl(data, out int processed);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace Base58Encoding.Tests;
2+
3+
public class SimpleLeadingZerosTest
4+
{
5+
[Fact]
6+
public void BitcoinAddress_CountLeadingZerosMultipleWays_SameResult()
7+
{
8+
var address = "1111111111111111111114oLvT2";
9+
var decoded = Base58.Bitcoin.Decode(address);
10+
11+
// Count leading zeros manually
12+
int manualCount = 0;
13+
for (int i = 0; i < decoded.Length; i++)
14+
{
15+
if (decoded[i] != 0) break;
16+
manualCount++;
17+
}
18+
19+
// Test SIMD
20+
int simdCount = Base58.CountLeadingZerosSimd(decoded, out int processed);
21+
var simdScalarCount = 0;
22+
if (simdCount >= processed)
23+
{
24+
int remaining = Base58.CountLeadingZerosScalar(decoded.AsSpan(simdCount));
25+
simdScalarCount = simdCount + remaining;
26+
}
27+
28+
Assert.Equal(simdScalarCount, manualCount);
29+
}
30+
}
Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<TargetFrameworks>net9.0;net10.0</TargetFrameworks>
5-
<ImplicitUsings>enable</ImplicitUsings>
6-
<Nullable>enable</Nullable>
3+
<PropertyGroup>
4+
<TargetFrameworks>net9.0;net10.0</TargetFrameworks>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
77

8-
<PackageId>Base58Encoding</PackageId>
9-
<Authors>Nikolay Zdravkov</Authors>
10-
<Description>A high-performance Base58 encoding/decoding library for .NET</Description>
11-
<PackageTags>base58;encoding;bitcoin;cryptocurrency</PackageTags>
12-
<PackageProjectUrl>https://github.com/unsafePtr/Base58Encoding</PackageProjectUrl>
13-
<RepositoryUrl>https://github.com/unsafePtr/Base58Encoding</RepositoryUrl>
14-
<PackageLicenseExpression>MIT</PackageLicenseExpression>
15-
<PackageReadmeFile>README.md</PackageReadmeFile>
16-
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
17-
</PropertyGroup>
8+
<PackageId>Base58Encoding</PackageId>
9+
<Authors>Nikolay Zdravkov</Authors>
10+
<Description>A high-performance Base58 encoding/decoding library for .NET</Description>
11+
<PackageTags>base58;encoding;bitcoin;cryptocurrency</PackageTags>
12+
<PackageProjectUrl>https://github.com/unsafePtr/Base58Encoding</PackageProjectUrl>
13+
<RepositoryUrl>https://github.com/unsafePtr/Base58Encoding</RepositoryUrl>
14+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
15+
<PackageReadmeFile>README.md</PackageReadmeFile>
16+
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
17+
</PropertyGroup>
1818

19-
<ItemGroup>
20-
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
21-
<_Parameter1>Base58Encoding.Benchmarks</_Parameter1>
22-
</AssemblyAttribute>
23-
</ItemGroup>
19+
<ItemGroup>
20+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
21+
<_Parameter1>Base58Encoding.Benchmarks</_Parameter1>
22+
</AssemblyAttribute>
23+
</ItemGroup>
24+
<ItemGroup>
25+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
26+
<_Parameter1>Base58Encoding.Tests</_Parameter1>
27+
</AssemblyAttribute>
28+
</ItemGroup>
2429

25-
<ItemGroup>
26-
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
27-
</ItemGroup>
30+
<ItemGroup>
31+
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
32+
</ItemGroup>
2833

2934
</Project>

src/Base58Encoding/CountLeading.Base58.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
using System.Runtime.Intrinsics;
55

66
namespace Base58Encoding;
7+
78
public partial class Base58
89
{
910
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1011
internal static int CountLeadingZeros(ReadOnlySpan<byte> data)
1112
{
12-
if (data.Length == 0)
13-
return 0;
14-
15-
if (data.Length < 16)
13+
if (data.Length < 64)
1614
return CountLeadingZerosScalar(data);
1715

1816
int count = CountLeadingZerosSimd(data, out int processed);

0 commit comments

Comments
 (0)