Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base58 perfomance patch #3186

Merged
merged 26 commits into from
Dec 19, 2024
Merged
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d9379be
Base58 perfomance improvments
kzorin52 Mar 28, 2024
66bbd57
Fix usings
kzorin52 Mar 28, 2024
8769111
Update src/Neo/Cryptography/Base58.cs
Jim8y Mar 28, 2024
fb882ca
Base58 improvments #2
kzorin52 Mar 29, 2024
194c456
Update src/Neo/Cryptography/Base58.cs
shargon Mar 29, 2024
a1ce6ab
Merge branch 'master' into base58-patch
Jim8y Apr 4, 2024
6b76b85
Merge branch 'master' into base58-patch
Jim8y Apr 11, 2024
0b06541
Merge branch 'master' into base58-patch
cschuchardt88 May 16, 2024
696318c
Merge branch 'master' into base58-patch
Jim8y May 17, 2024
e437511
Merge branch 'master' into base58-patch
shargon May 20, 2024
f8c7bc8
Merge branch 'master' into base58-patch
cschuchardt88 Jun 9, 2024
9a338e6
Merge branch 'master' into base58-patch
cschuchardt88 Jun 27, 2024
faeb909
fix perfomance
kzorin52 Oct 14, 2024
1b641d8
remove Ext, further optimisations
kzorin52 Oct 14, 2024
1a3c0c2
Merge branch 'master' into base58-patch
kzorin52 Oct 16, 2024
bd3a205
Clean
shargon Oct 17, 2024
2682e8b
format
kzorin52 Oct 18, 2024
babf4a4
Merge branch 'master' into base58-patch
Jim8y Nov 6, 2024
a1ff531
Merge branch 'master' into base58-patch
shargon Nov 6, 2024
8c2c577
Reduce array
shargon Nov 6, 2024
ea3f6d8
reuse var
shargon Nov 6, 2024
8840fb3
same name as before
shargon Nov 6, 2024
bfd9ae1
Merge branch 'master' into base58-patch
shargon Dec 5, 2024
3163eb3
Merge branch 'master' into base58-patch
cschuchardt88 Dec 9, 2024
4e598fb
Merge branch 'master' into base58-patch
Jim8y Dec 19, 2024
260c9fe
Merge branch 'master' into base58-patch
NGDAdmin Dec 19, 2024
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
40 changes: 31 additions & 9 deletions src/Neo/Cryptography/Base58.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
// modifications are permitted.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using static Neo.Helper;

namespace Neo.Cryptography
{
Expand All @@ -27,6 +28,9 @@ public static class Base58
/// </summary>
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

private static readonly char s_zeroChar = Alphabet[0];
private static readonly Lazy<IReadOnlyDictionary<char, int>> s_alphabetDic = new(() => Enumerable.Range(0, Alphabet.Length).ToDictionary(t => Alphabet[t], t => t));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cost more in the current code in resources of memory management for the GC in dotnet.


/// <summary>
/// Converts the specified <see cref="string"/>, which encodes binary data as base-58 digits, to an equivalent byte array. The encoded <see cref="string"/> contains the checksum of the binary data.
/// </summary>
Expand Down Expand Up @@ -74,19 +78,27 @@ public static byte[] Decode(string input)
var bi = BigInteger.Zero;
for (int i = 0; i < input.Length; i++)
{
int digit = Alphabet.IndexOf(input[i]);
if (digit < 0)
if (!s_alphabetDic.Value.TryGetValue(input[i], out var digit))
shargon marked this conversation as resolved.
Show resolved Hide resolved
throw new FormatException($"Invalid Base58 character '{input[i]}' at position {i}");
bi = bi * Alphabet.Length + digit;
}

// Encode BigInteger to byte[]
// Leading zero bytes get encoded as leading `1` characters
int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count();
var leadingZeros = new byte[leadingZeroCount];
if (bi.IsZero) return leadingZeros;
var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true);
return Concat(leadingZeros, bytesWithoutLeadingZeros);
int leadingZeroCount = LeadingBase58Zeros(input);
if (bi.IsZero)
{
return new byte[leadingZeroCount];
}

int decodedSize = bi.GetByteCount(true) + leadingZeroCount;
shargon marked this conversation as resolved.
Show resolved Hide resolved

Span<byte> result = decodedSize <= 128
? stackalloc byte[decodedSize]
: new byte[decodedSize];

_ = bi.TryWriteBytes(result[leadingZeroCount..], out _, true, true);
shargon marked this conversation as resolved.
Show resolved Hide resolved
return result.ToArray();
}

/// <summary>
Expand All @@ -111,9 +123,19 @@ public static string Encode(ReadOnlySpan<byte> input)
// Append `1` for each leading 0 byte
for (int i = 0; i < input.Length && input[i] == 0; i++)
{
sb.Insert(0, Alphabet[0]);
sb.Insert(0, s_zeroChar);
}
return sb.ToString();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LeadingBase58Zeros(string collection)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
var i = 0;
var len = collection.Length;
for (; i < len && collection[i] == s_zeroChar; i++) { }

return i;
}
}
}
Loading