Skip to content

Commit

Permalink
Decision to give priority to long slices over short ones. Given how t…
Browse files Browse the repository at this point in the history
…he size of slices can vary it is better to lose a bit (10%) on smaller slices (less than 20 bytes) and to win big on the bigger ones.

Before 16 bytes the gain is -10%
After 24 bytes the gain is 10%
After 64 bytes the gain is 2x
After 128 bytes the gain is 4x.

We should control the distribution of typical workloads over time.
  • Loading branch information
redknightlois committed Apr 23, 2015
1 parent 1e89835 commit cca7676
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 41 deletions.
3 changes: 3 additions & 0 deletions Raven.Database/Raven.Database.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<DocumentationFile>
</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -65,6 +66,7 @@
</DocumentationFile>
<NoWarn>1607, 1591</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
Expand All @@ -81,6 +83,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Esent.Interop">
Expand Down
65 changes: 65 additions & 0 deletions Raven.Voron/Voron.Tests/Util/Hashing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Voron.Util;
using Xunit;

namespace Voron.Tests.Util
{
public class HashingTests
{

[Fact]
public void XXHash32()
{
string value = "abcd";
uint result = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 0);
uint expected = 0xA3643705;
Assert.Equal(expected, result);

value = "abc";
result = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 0);
expected = 0x32D153FF;
Assert.Equal(expected, result);

value = "heiå";
result = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 0);
expected = 0xDB5ABCCC;
Assert.Equal(expected, result);

value = "κόσμε";
result = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 0);
expected = 0xD855F606;
Assert.Equal(expected, result);

value = "asdfasdfasdfasdfasdfasdfasdfuqrewpuqpuqruepoiqiwoerpuqowieruqwlekjrqwernq/wemnrq.,wemrn";
var bytes = Encoding.UTF8.GetBytes(value);
result = Hashing.XXHash32.Calculate(bytes);
expected = 3571373779;
Assert.Equal(expected, result);
}


[Fact]
public void NotEquivalenceOfBytesWithString()
{
string value = "abcd";
uint result = Hashing.XXHash32.CalculateRaw(value, seed: 10);
uint expected = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 10);
Assert.NotEqual(expected, result);

value = "abc";
result = Hashing.XXHash32.CalculateRaw(value, seed: 10);
expected = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 10);
Assert.NotEqual(expected, result);

value = "κόσμε";
result = Hashing.XXHash32.CalculateRaw(value, seed: 10);
expected = Hashing.XXHash32.Calculate(Encoding.UTF8.GetBytes(value), seed: 10);
Assert.NotEqual(expected, result);
}

}
}
1 change: 1 addition & 0 deletions Raven.Voron/Voron.Tests/Voron.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
<Compile Include="Trees\TreesWithPrefixedKeys.cs" />
<Compile Include="Trees\Updates.cs" />
<Compile Include="Util\CrcTests.cs" />
<Compile Include="Util\Hashing.cs" />
<Compile Include="Util\ImmutableAppendOnlyTests.cs" />
<Compile Include="Util\StreamExtensions.cs" />
</ItemGroup>
Expand Down
64 changes: 23 additions & 41 deletions Raven.Voron/Voron/Slice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public sealed unsafe class Slice : MemorySlice
public static Slice BeforeAllKeys = new Slice(SliceOptions.BeforeAllKeys);
public static Slice Empty = new Slice(new byte[0]);

internal byte[] Array;
internal byte[] Array;
internal byte* Pointer;

public Slice(SliceOptions options)
Expand Down Expand Up @@ -80,48 +80,30 @@ public override bool Equals(object obj)

public override int GetHashCode()
{
if (Array != null)
return ComputeHashArray();
return ComputeHashPointer();
}

private int ComputeHashPointer()
{
unchecked
{
const int p = 16777619;
int hash = (int)2166136261;

for (int i = 0; i < Size; i++)
hash = (hash ^ Pointer[i]) * p;

hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
// Given how the size of slices can vary it is better to lose a bit (10%) on smaller slices
// (less than 20 bytes) and to win big on the bigger ones.
//
// After 24 bytes the gain is 10%
// After 64 bytes the gain is 2x
// After 128 bytes the gain is 4x.
//
// We should control the distribution of this over time.
unsafe
{
if (Array != null)
{
fixed (byte* arrayPtr = Array)
{
return (int)Hashing.XXHash32.CalculateInline(arrayPtr, Size);
}
}
else
{
return (int)Hashing.XXHash32.CalculateInline(Pointer, Size);
}
}
}

private int ComputeHashArray()
{
unchecked
{
const int p = 16777619;
int hash = (int)2166136261;

for (int i = 0; i < Size; i++)
hash = (hash ^ Array[i]) * p;

hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
}

public override string ToString()
{
Expand Down
Loading

0 comments on commit cca7676

Please sign in to comment.