Skip to content

Commit

Permalink
Blake2b c.10% faster incremental hashing
Browse files Browse the repository at this point in the history
Copy only a part of ctx (h,t,f) needed for finalization. Pass vectors always by ref.
  • Loading branch information
buybackoff committed Dec 8, 2018
1 parent 4dae1bf commit 895e446
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 560 deletions.
51 changes: 28 additions & 23 deletions src/Spreads.Core/Algorithms/Hash/BLAKE2b/Blake2bContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ namespace Spreads.Algorithms.Hash
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public unsafe partial struct Blake2bContext
{
[StructLayout(LayoutKind.Sequential)]
internal struct Blake2bContextFinalizable
{
public fixed ulong h[HashWords];
public fixed ulong t[2];
public fixed ulong f[2];
}

public const int WordSize = sizeof(ulong);
public const int BlockWords = 16;
public const int BlockBytes = BlockWords * WordSize;
Expand All @@ -35,10 +43,9 @@ public unsafe partial struct Blake2bContext
0x1F83D9ABFB41BD6Bul, 0x5BE0CD19137E2179ul
};

private Blake2bContextFinalizable htf;

private fixed byte b[BlockBytes];
private fixed ulong h[HashWords];
private fixed ulong t[2];
private fixed ulong f[2];

#if NETCOREAPP2_1
private fixed ulong viv[HashWords];
Expand All @@ -51,9 +58,9 @@ public unsafe partial struct Blake2bContext
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void addLength(uint len)
{
t[0] += len;
if (t[0] < len)
t[1]++;
htf.t[0] += len;
if (htf.t[0] < len)
htf.t[1]++;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -89,8 +96,8 @@ internal void Init(int digestLength = HashBytes, ReadOnlySpan<byte> key = defaul
}

outlen = (uint)digestLength;
Unsafe.CopyBlock(ref Unsafe.As<ulong, byte>(ref h[0]), ref Unsafe.As<ulong, byte>(ref iv[0]), HashBytes);
h[0] ^= 0x01010000u ^ (keylen << 8) ^ outlen;
Unsafe.CopyBlock(ref Unsafe.As<ulong, byte>(ref htf.h[0]), ref Unsafe.As<ulong, byte>(ref iv[0]), HashBytes);
htf.h[0] ^= 0x01010000u ^ (keylen << 8) ^ outlen;

#if NETCOREAPP2_1
if (Sse41.IsSupported)
Expand Down Expand Up @@ -119,7 +126,7 @@ private static void ThrowBadKeyLength()
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(DirectBuffer input)
public void Update(in DirectBuffer input)
{
uint inlen = (uint)input.Length;

Expand All @@ -135,20 +142,16 @@ public void Update(DirectBuffer input)
Unsafe.CopyBlockUnaligned(s->b + c, input._pointer, blockrem);
}
addLength(BlockBytes);

compress(s, s->b);

clen += blockrem;
inlen -= blockrem;
c = 0u;
}




if (inlen + clen > BlockBytes)
{

byte* pinput = input._pointer;

while (inlen > BlockBytes)
Expand All @@ -174,20 +177,20 @@ public void Update(DirectBuffer input)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void finish(Span<byte> hash)
{
if (f[0] != 0)
if (htf.f[0] != 0)
{ ThrowHashAlreadyFinalized(); }

if (c < BlockBytes)
{ Unsafe.InitBlockUnaligned(ref b[c], 0, BlockBytes - c); }

addLength(c);
f[0] = unchecked((ulong)~0);
htf.f[0] = unchecked((ulong)~0);
var s = (Blake2bContext*)Unsafe.AsPointer(ref Unsafe.AsRef(this));
{
compress(s, s->b);
}

Unsafe.CopyBlock(ref hash[0], ref Unsafe.As<ulong, byte>(ref h[0]), outlen);
Unsafe.CopyBlock(ref hash[0], ref Unsafe.As<ulong, byte>(ref htf.h[0]), outlen);
}

private static void ThrowHashAlreadyFinalized()
Expand All @@ -196,18 +199,20 @@ private static void ThrowHashAlreadyFinalized()
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void finish(in Blake2bContext ctx, Span<byte> hash)
private static void finish(ref Blake2bContext ctx1, Span<byte> hash)
{
var ctx1 = ctx;
var prevHtf = ctx1.htf;
// var ctx1 = ctx;
if (ctx1.c < BlockBytes)
Unsafe.InitBlockUnaligned(ref ctx1.b[ctx1.c], 0, BlockBytes - ctx1.c);

ctx1.addLength(ctx1.c);
ctx1.f[0] = unchecked((ulong)~0);
ctx1.htf.f[0] = unchecked((ulong)~0);
var s = (Blake2bContext*)Unsafe.AsPointer(ref Unsafe.AsRef(ctx1));
compress(s, s->b);

Unsafe.CopyBlock(ref hash[0], ref Unsafe.As<ulong, byte>(ref ctx1.h[0]), ctx1.outlen);
Unsafe.CopyBlock(ref hash[0], ref Unsafe.As<ulong, byte>(ref ctx1.htf.h[0]), ctx1.outlen);
ctx1.htf = prevHtf;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -225,15 +230,15 @@ public bool TryFinish(Span<byte> output, out int bytesWritten)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryFinish(in Blake2bContext ctx, Span<byte> output, out int bytesWritten)
public static bool TryFinish(ref Blake2bContext ctx, Span<byte> output, out int bytesWritten)
{
if (output.Length < ctx.outlen)
{
bytesWritten = 0;
return false;
}

finish(in ctx, output);
finish(ref ctx, output);
bytesWritten = (int)ctx.outlen;
return true;
}
Expand Down
38 changes: 19 additions & 19 deletions src/Spreads.Core/Algorithms/Hash/BLAKE2b/Blake2bScalar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ unsafe private static void mixScalar(Blake2bContext* s, ulong* m)
ulong m14 = m[14];
ulong m15 = m[15];

ulong v00 = s->h[0];
ulong v01 = s->h[1];
ulong v02 = s->h[2];
ulong v03 = s->h[3];
ulong v04 = s->h[4];
ulong v05 = s->h[5];
ulong v06 = s->h[6];
ulong v07 = s->h[7];
ulong v00 = s->htf.h[0];
ulong v01 = s->htf.h[1];
ulong v02 = s->htf.h[2];
ulong v03 = s->htf.h[3];
ulong v04 = s->htf.h[4];
ulong v05 = s->htf.h[5];
ulong v06 = s->htf.h[6];
ulong v07 = s->htf.h[7];

ulong v08 = 0x6A09E667F3BCC908ul;
ulong v09 = 0xBB67AE8584CAA73Bul;
Expand All @@ -53,9 +53,9 @@ unsafe private static void mixScalar(Blake2bContext* s, ulong* m)
ulong v14 = 0x1F83D9ABFB41BD6Bul;
ulong v15 = 0x5BE0CD19137E2179ul;

v12 ^= s->t[0];
v13 ^= s->t[1];
v14 ^= s->f[0];
v12 ^= s->htf.t[0];
v13 ^= s->htf.t[1];
v14 ^= s->htf.f[0];

//ROUND 1
v00 += m00;
Expand Down Expand Up @@ -1605,14 +1605,14 @@ unsafe private static void mixScalar(Blake2bContext* s, ulong* m)
v06 ^= v11;
v06 = ror(v06, 63);

s->h[0] ^= v00 ^ v08;
s->h[1] ^= v01 ^ v09;
s->h[2] ^= v02 ^ v10;
s->h[3] ^= v03 ^ v11;
s->h[4] ^= v04 ^ v12;
s->h[5] ^= v05 ^ v13;
s->h[6] ^= v06 ^ v14;
s->h[7] ^= v07 ^ v15;
s->htf.h[0] ^= v00 ^ v08;
s->htf.h[1] ^= v01 ^ v09;
s->htf.h[2] ^= v02 ^ v10;
s->htf.h[3] ^= v03 ^ v11;
s->htf.h[4] ^= v04 ^ v12;
s->htf.h[5] ^= v05 ^ v13;
s->htf.h[6] ^= v06 ^ v14;
s->htf.h[7] ^= v07 ^ v15;
}
}
}
Loading

0 comments on commit 895e446

Please sign in to comment.