D hash table comparison benchmark
Nathan S.
no.public.email at example.com
Tue Jun 26 02:44:27 UTC 2018
Benchmark code:
dub.sdl
```
name "hashbench"
description "D hashtable comparison."
dependency "emsi_containers" version="~>0.7.0"
dependency "memutils" version="~>0.4.11"
dependency "vibe-d:utils" version="~>0.8.4"
dependency "jive" version="~>0.2.0"
//dependency "collections" version="~>0.1.0"
//dependency "tanya" version="~>0.10.0"
//dependency "kontainer" version="~>0.0.2"
```
app.d
```d
int nthKey(in uint n) @nogc nothrow pure @safe
{
// Can be any invertible function.
// The goal is to map [0 .. N] to a sequence not in ascending
order.
int h = cast(int) (n + 1);
h = (h ^ (h >>> 16)) * 0x85ebca6b;
h = (h ^ (n >>> 13)) * 0xc2b2ae35;
return h ^ (h >>> 16);
}
pragma(inline, false)
uint hashBench(HashTable, Args...)(in uint N, in uint seed, Args
initArgs)
{
static if (initArgs.length)
HashTable hashtable = HashTable(initArgs);
else // Separate branch needed for builtin AA.
HashTable hashtable;
foreach (uint n; 0 .. N)
hashtable[nthKey(n)] = n + seed;
uint sum;
foreach_reverse (uint n; 0 .. N/2)
sum += hashtable[nthKey(n)];
foreach_reverse(uint n; N/2 .. N)
sum += hashtable[nthKey(n)];
return sum;
}
pragma(inline, false)
uint hashBenchReuse(HashTable)(in uint N, in uint seed, ref
HashTable hashtable)
{
foreach (uint n; 0 .. N)
hashtable[nthKey(n)] = n + seed;
uint sum;
foreach_reverse (uint n; 0 .. N/2)
sum += hashtable[nthKey(n)];
foreach_reverse(uint n; N/2 .. N)
sum += hashtable[nthKey(n)];
return sum;
}
enum benchmarkCode(string name, string signature = name) =
`
{
sw.reset();
result = 0;
sw.start();
foreach (_; 0 .. M)
{
result += hashBench!(`~signature~`)(N, result);
}
sw.stop();
string s = "`~name~`";
printf("[checksum %d] %3d msecs %s\n",
result, sw.peek.total!"msecs", &s[0]);
}
`;
enum benchmarkCodeReuse(string name, string signature = name) =
`
{
sw.reset();
result = 0;
sw.start();
`~signature~` hashtable;
foreach (_; 0 .. M)
{
result += hashBenchReuse!(`~signature~`)(N,
result, hashtable);
}
sw.stop();
string s = "`~name~`";
printf("(checksum %d) %3.2f msecs %s\n",
result, sw.peek.total!"usecs" / 1000.0, &s[0]);
}
`;
void main(string[] args)
{
import std.datetime.stopwatch : AutoStart, StopWatch;
import core.stdc.stdio : printf, puts;
import std.experimental.allocator.gc_allocator : GCAllocator;
import std.experimental.allocator.mallocator : Mallocator;
alias BuiltinAA(K,V) = V[K];
import containers.hashmap : EMSI_HashMap = HashMap;
import memutils.hashmap : Memutils_HashMap = HashMap;
import vibe.utils.hashmap : Vibe_HashMap = HashMap;
import jive.map : Jive_Map = Map;
//import stdx.collections.hashtable : Stdx_Hashtable =
Hashtable;
//import tanya.container.hashtable : Tanya_HashTable =
HashTable;
//import kontainer.orderedAssocArray.orderedAssocArray :
Kontainer_OrderedAssocArray = OrderedAssocArray;
immutable uint N = args.length < 2 ? 100 :
() {
import std.conv : to;
auto result = to!uint(args[1]);
return (result == 0 ? 100 : result);
}();
immutable M = N <= 500_000 ? (1000_000 / N) : 2;
enum topLevelRepetitions = 3;
printf("Hashtable benchmark N (size) = %d (repetitions) =
%d\n", N, M);
StopWatch sw = StopWatch(AutoStart.no);
uint result;
version(all)
{
puts("\n=Results (new hashtables)=");
foreach (_repetition; 0 .. topLevelRepetitions)
{
printf("*Trial #%d*\n", _repetition+1);
mixin(benchmarkCode!("built-in AA", "BuiltinAA!(int,
int)"));
mixin(benchmarkCode!("containers.hashmap
w/Mallocator", "EMSI_HashMap!(int, int, Mallocator)"));
mixin(benchmarkCode!("containers.hashmap
w/GCAllocator", "EMSI_HashMap!(int, int, GCAllocator)"));
mixin(benchmarkCode!("memutils.hashmap",
"Memutils_HashMap!(int,int)"));
mixin(benchmarkCode!("vibe.utils.hashmap",
"Vibe_HashMap!(int,int)"));
mixin(benchmarkCode!("jive.map",
"Jive_Map!(int,int)"));
//mixin(benchmarkCode!("stdx.collections.hashtable",
"Stdx_Hashtable!(int,int)"));
//mixin(benchmarkCode!("tanya.container.hashtable",
"Tanya_HashTable!(int,int)"));
//mixin(benchmarkCode!("kontainer.orderedAssocArray.orderedAssocArray", "Kontainer_OrderedAssocArray!(int,int)"));
}
}
version(all)
{
puts("\n=Results (reusing hashtables)=\n");
foreach (_repetition; 0 .. topLevelRepetitions)
{
printf("*Trial #%d*\n", _repetition+1);
mixin(benchmarkCodeReuse!("built-in AA",
"BuiltinAA!(int, int)"));
mixin(benchmarkCodeReuse!("containers.hashmap
w/Mallocator", "EMSI_HashMap!(int, int, Mallocator)"));
mixin(benchmarkCodeReuse!("containers.hashmap
w/GCAllocator", "EMSI_HashMap!(int, int, GCAllocator)"));
mixin(benchmarkCodeReuse!("memutils.hashmap",
"Memutils_HashMap!(int,int)"));
mixin(benchmarkCodeReuse!("vibe.utils.hashmap",
"Vibe_HashMap!(int,int)"));
mixin(benchmarkCodeReuse!("jive.map",
"Jive_Map!(int,int)"));
//mixin(benchmarkCodeReuse!("stdx.collections.hashtable",
"Stdx_Hashtable!(int,int)"));
//mixin(benchmarkCodeReuse!("tanya.container.hashtable",
"Tanya_HashTable!(int,int)"));
//mixin(benchmarkCodeReuse!("kontainer.orderedAssocArray.orderedAssocArray", "Kontainer_OrderedAssocArray!(int,int)"));
}
}
}
```
More information about the Digitalmars-d
mailing list