├── hash-fillrate-def-FNV1A.png ├── hash-fillrate-def-OOAT_HARD.png ├── .whitesource ├── .gitignore ├── cachegrind-cost.pl ├── sdbm+djb2.patch ├── hash-result.pl ├── hash.stats ├── crc.patch ├── 0001-DH-debug-hash-fill-size-and-collisions.patch ├── LICENSE ├── README.md └── log.hash-speed /hash-fillrate-def-FNV1A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rurban/perl-hash-stats/HEAD/hash-fillrate-def-FNV1A.png -------------------------------------------------------------------------------- /hash-fillrate-def-OOAT_HARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rurban/perl-hash-stats/HEAD/hash-fillrate-def-OOAT_HARD.png -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "generalSettings": { 3 | "shouldScanRepo": true 4 | }, 5 | "checkRunSettings": { 6 | "vulnerableCheckRunConclusionLevel": "failure" 7 | } 8 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | -------------------------------------------------------------------------------- /cachegrind-cost.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # apply cost model to cachegrind results 3 | 4 | # Usage: 5 | # valgrind --tool=cachegrind ./miniperl -e'my %h = ("foo" => 1); $h{foo} for 0..100' \ 6 | # 2>&1 > log.hash 7 | # perl cachegrind-cost.pl log.hash |sort -nk2 -t$'\t' 8 | 9 | my $cost = 0; 10 | LINE: while (<>) { 11 | unless (/^==\d+==/) { 12 | if ($cost) { 13 | print "\t$cost\n"; 14 | } 15 | chomp; 16 | print; 17 | $cost = 0; 18 | next LINE; 19 | } 20 | s/^==\d+== //; 21 | my ($a,$b,$n) = split ' '; 22 | $n =~ s/,//g; 23 | 24 | if (/I\s+refs:/) { 25 | $cost += $n; 26 | } elsif (/[DI]1\s+misses:/) { 27 | $cost += $n + 10; 28 | } elsif (/(LIi|LLd)\s+misses:/) { 29 | $cost += $n + 200; 30 | } 31 | } 32 | 33 | if ($cost) { 34 | print "\t$cost\n"; 35 | } 36 | -------------------------------------------------------------------------------- /sdbm+djb2.patch: -------------------------------------------------------------------------------- 1 | diff --git hv_func.h hv_func.h 2 | index 191912a..961d7bd 100644 3 | --- hv_func.h 4 | +++ hv_func.h 5 | @@ -455,9 +465,10 @@ S_perl_hash_murmur3(const unsigned char * const seed, const unsigned char *ptr, 6 | PERL_STATIC_INLINE U32 7 | S_perl_hash_djb2(const unsigned char * const seed, const unsigned char *str, const STRLEN len) { 8 | const unsigned char * const end = (const unsigned char *)str + len; 9 | - U32 hash = *((U32*)seed + len); 10 | + U32 hash = *((U32*)seed); 11 | while (str < end) { 12 | - hash = ((hash << 5) + hash) + *str++; 13 | + hash = ((hash << 5) + hash) + *str; 14 | + str++; 15 | } 16 | return hash; 17 | } 18 | @@ -465,9 +476,10 @@ S_perl_hash_djb2(const unsigned char * const seed, const unsigned char *str, con 19 | PERL_STATIC_INLINE U32 20 | S_perl_hash_sdbm(const unsigned char * const seed, const unsigned char *str, const STRLEN len) { 21 | const unsigned char * const end = (const unsigned char *)str + len; 22 | - U32 hash = *((U32*)seed + len); 23 | + U32 hash = *((U32*)seed); 24 | while (str < end) { 25 | - hash = (hash << 6) + (hash << 16) - hash + *str++; 26 | + hash = (hash << 6) + (hash << 16) - hash + *str; 27 | + str++; 28 | } 29 | return hash; 30 | } 31 | -------------------------------------------------------------------------------- /hash-result.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -an 2 | # test -DH hash collisions 3 | 4 | # Usage: 5 | # apply -DH patch at https://github.com/rurban/perl/commit/b975d736cfe40a9cf51ec0a44aaba0322fd04347 6 | # define PERL_HASH_FUNC_ONE_AT_A_TIME in config.h 7 | # make test 2> log.hash.ONE_AT_A_TIME 8 | # kill perl hanging at cpan/Test-Simple/t/utf8.t and ext/PerlIO-encoding/t/nolooping.t 9 | # ./hash-result.pl log.hash.ONE_AT_A_TIME | tee hash.result.ONE_AT_A_TIME 10 | 11 | # skip non-conformant lines 12 | # STDERR might get garbled by tests and we dont try to fix around this 13 | # we will not print to a special filehandle just for -DH 14 | 15 | next unless ($F[0] =~ /^\d+$/ 16 | and $F[1] =~ /^\d+$/ 17 | and $F[2] =~ /^\d+$/ 18 | and (@F == 3 or (@F == 4 and $F[3] !~ /^\d+$/))); 19 | 20 | $F{0}{$F[0]}++; 21 | $F{1}{$F[1]}++; 22 | $F{2}{$F[2]}++; 23 | $F{3}{$F[3]}++ if $F[3]; 24 | $n++; 25 | 26 | END{ 27 | my %i = ( 28 | 0 => 'keys', 29 | 1 => 'size', 30 | 2 => 'coll', 31 | 3 => 'op', 32 | ); 33 | my ($median_cnt, $n_2, $median) = (0, $n >> 1, 0); 34 | for $i (0..3) { 35 | print "$i $i{$i}:\n"; 36 | for $k (sort {$a<=>$b} keys $F{$i}) { 37 | print "\t",$k,"\t",$F{$i}{$k},"x\n"; 38 | if ($i == 0) { 39 | if ($median_cnt < $n_2) { 40 | $median_cnt += $F{0}{$k}; 41 | } elsif (!$median) { 42 | $median = $k; 43 | } 44 | } 45 | } 46 | print "\n"; 47 | } 48 | my $cost = 0; 49 | for my $k (sort {$a<=>$b} keys $F{2}) { 50 | $cost += $F{2}{$k} * $k; 51 | } 52 | print "collision cost: $cost / # lines: $n\n"; 53 | print sprintf("ratio: %0.03f\n", $cost / $n); 54 | 55 | my $keys = 0; 56 | $keys += $_ * $F{0}{$_} for keys $F{0}; 57 | print sprintf("key size: avg = %0.03f, median = %d\n", $keys / $n, $median); 58 | } 59 | -------------------------------------------------------------------------------- /hash.stats: -------------------------------------------------------------------------------- 1 | Counting the collisions with perl hash tables per function. 2 | (linear chaining in a linked list, subject to collision attacks) 3 | 4 | collisions (less is better) 5 | CRC32 1.078 6 | ONE_AT_A_TIME_HARD 1.092 7 | SIPHASH 1.091 8 | ONE_AT_A_TIME 1.098 9 | ONE_AT_A_TIME_OLD 10 | SDBM 11 | SUPERFAST 12 | DJB2 13 | MURMUR3 1.105 14 | 15 | See http://blogs.perl.org/users/rurban/2014/04/statistics-for-perl-hash-tables.html 16 | and https://gist.github.com/rurban/10439033 17 | 18 | $ tail -n20 hash.result.CRC32 19 | 2 coll: 20 | 0 26895000x 21 | 1 98179685x 22 | 2 25832401x 23 | 3 5582369x 24 | 4 660175x 25 | 5 53429x 26 | 6 5726x 27 | 7 157x 28 | 8 5x 29 | 30 | 3 op: 31 | DEL+ 2371595x 32 | DEL- 63408x 33 | - 41471245x 34 | DELpl 6x 35 | 36 | collision cost: 169534934 / # lines: 157208947 37 | ratio: 1.078 38 | 39 | $ tail -n20 hash.result.ONE_AT_A_TIME_HARD 40 | 41 | 2 coll: 42 | 0 19075964x 43 | 1 76051725x 44 | 2 19869990x 45 | 3 4091870x 46 | 4 577088x 47 | 5 46416x 48 | 6 16933x 49 | 7 346x 50 | 8 23x 51 | 52 | 3 op: 53 | DEL- 47556x 54 | - 30553435x 55 | DEL+ 1521038x 56 | DELpl 6x 57 | 58 | collision cost: 130711951 / # lines: 119730355 59 | ratio: 1.092 60 | 61 | $ tail -n20 hash.result.MURMUR3 62 | 63 | 2 coll: 64 | 0 24821274x 65 | 1 99735474x 66 | 2 26327227x 67 | 3 6066529x 68 | 4 862574x 69 | 5 76627x 70 | 6 6877x 71 | 7 276x 72 | 8 20x 73 | 74 | 3 op: 75 | DEL- 65262x 76 | DEL+ 2379381x 77 | - 41634279x 78 | DELpl 6x 79 | 80 | collision cost: 174466300 / # lines: 157896878 81 | ratio: 1.105 82 | 83 | $ tail -n20 hash.result.SIPHASH 84 | 85 | 2 coll: 86 | 0 26314186x 87 | 1 99114872x 88 | 2 25655322x 89 | 3 5749479x 90 | 4 888039x 91 | 5 205159x 92 | 6 3449x 93 | 7 399x 94 | 8 46x 95 | 9 16x 96 | 97 | 3 op: 98 | DEL- 65445x 99 | DELpl 6x 100 | DEL+ 2379395x 101 | - 41638164x 102 | 103 | collision cost: 172275903 / # lines: 157930967 104 | ratio: 1.091 105 | 106 | $ tail -n20 hash.result.ONE_AT_A_TIME 107 | 2 coll: 108 | 0 25867206x 109 | 1 98008406x 110 | 2 27351918x 111 | 3 5588012x 112 | 4 836805x 113 | 5 68047x 114 | 6 6104x 115 | 7 203x 116 | 8 10x 117 | 9 1x 118 | 10 53x 119 | 120 | 3 op: 121 | DELpl 6x 122 | - 41623366x 123 | DEL+ 2378959x 124 | DEL- 65074x 125 | 126 | collision cost: 173202397 / # lines: 157726765 127 | ratio: 1.098 128 | 129 | See more in the individual files for now. Will be updated at the end my testruns. 130 | CRC32 is so far by far the fastest and produces the least collisions. 131 | It has a high bias (avalanche), but this didn't show up in this avg testdata. 132 | -------------------------------------------------------------------------------- /crc.patch: -------------------------------------------------------------------------------- 1 | Just trying performance and quality HW CRC32 2 | In real code this should be checked in perl_init for CPU features. 3 | 4 | I guess the hash function is not quite kosher yet, but gives a 5 | rough estimate for the data I'm looking for: performance and 6 | number of collisions. 7 | 8 | diff --git hv_func.h hv_func.h 9 | index 191912a..38134bc 100644 10 | --- hv_func.h 11 | +++ hv_func.h 12 | @@ -21,6 +21,7 @@ 13 | || defined(PERL_HASH_FUNC_ONE_AT_A_TIME) \ 14 | || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD) \ 15 | || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_OLD) \ 16 | + || defined(PERL_HASH_FUNC_CRC32) \ 17 | ) 18 | #define PERL_HASH_FUNC_ONE_AT_A_TIME_HARD 19 | #endif 20 | @@ -57,6 +58,10 @@ 21 | # define PERL_HASH_FUNC "ONE_AT_A_TIME_OLD" 22 | # define PERL_HASH_SEED_BYTES 4 23 | # define PERL_HASH(hash,str,len) (hash)= S_perl_hash_old_one_at_a_time(PERL_HASH_SEED,(U8*)(str),(len)) 24 | +#elif defined(PERL_HASH_FUNC_CRC32) 25 | +# define PERL_HASH_FUNC "CRC32" 26 | +# define PERL_HASH_SEED_BYTES 4 27 | +# define PERL_HASH(hash,str,len) (hash)= S_perl_hash_crc32(PERL_HASH_SEED,(U8*)(str),(len)) 28 | #endif 29 | 30 | #ifndef PERL_HASH 31 | @@ -552,6 +557,49 @@ S_perl_hash_old_one_at_a_time(const unsigned char * const seed, const unsigned c 32 | return (hash + (hash << 15)); 33 | } 34 | 35 | +#ifdef __SSE4_2__ 36 | +#include 37 | +#endif 38 | + 39 | +/* Byte-boundary alignment issues */ 40 | +#define ALIGN_SIZE 0x08UL 41 | +#define ALIGN_MASK (ALIGN_SIZE - 1) 42 | +#define CALC_CRC(op, crc, type, buf, len) \ 43 | + do { \ 44 | + for (; (len) >= sizeof (type); (len) -= sizeof(type), buf += sizeof (type)) { \ 45 | + (crc) = op((crc), *(type *) (buf)); \ 46 | + } \ 47 | + } while(0) 48 | + 49 | +PERL_STATIC_INLINE U32 50 | +S_perl_hash_crc32(const unsigned char * const seed, const unsigned char *str, const STRLEN inlen) { 51 | + /* tested + len: much higher collision costs, not needed for \0, safe even with PERL_HASH_SEED=0 */ 52 | + U32 hash = *((U32*)seed); 53 | + const char* buf = (const char*)str; 54 | + STRLEN len = inlen; 55 | + 56 | +#ifdef __SSE4_2__ 57 | + /* 32 bit only */ 58 | + hash ^= 0xFFFFFFFF; 59 | + /* Align the input to the word boundary */ 60 | + for (; (len > 0) && ((size_t)buf & ALIGN_MASK); len--, buf++) { 61 | + hash = _mm_crc32_u8(hash, *buf); 62 | + } 63 | + 64 | +#ifdef __x86_64__ 65 | + CALC_CRC(_mm_crc32_u64, hash, uint64_t, buf, len); 66 | +#endif 67 | + CALC_CRC(_mm_crc32_u32, hash, uint32_t, buf, len); 68 | + CALC_CRC(_mm_crc32_u16, hash, uint16_t, buf, len); 69 | + CALC_CRC(_mm_crc32_u8, hash, uint8_t, buf, len); 70 | +#else 71 | + #error SW crc32 not good. Need Intel SSE4 processor for PERL_HASH_FUNC_CRC32 72 | +#endif 73 | + 74 | + /* 32 bit only */ 75 | + return (hash ^ 0xFFFFFFFF); 76 | +} 77 | + 78 | /* legacy - only mod_perl should be doing this. */ 79 | #ifdef PERL_HASH_INTERNAL_ACCESS 80 | #define PERL_HASH_INTERNAL(hash,str,len) PERL_HASH(hash,str,len) 81 | -------------------------------------------------------------------------------- /0001-DH-debug-hash-fill-size-and-collisions.patch: -------------------------------------------------------------------------------- 1 | From b975d736cfe40a9cf51ec0a44aaba0322fd04347 Mon Sep 17 00:00:00 2001 2 | From: Reini Urban 3 | Date: Wed, 9 Apr 2014 00:31:07 -0500 4 | Subject: [PATCH] -DH debug hash fill, size and collisions 5 | 6 | for make test. testing quality of functions and collision strategy 7 | --- 8 | doop.c | 2 ++ 9 | hv.c | 17 +++++++++++++++++ 10 | t/TEST | 2 +- 11 | 3 files changed, 20 insertions(+), 1 deletion(-) 12 | 13 | diff --git doop.c doop.c 14 | index 5031af8..adf3c06 100644 15 | --- doop.c 16 | +++ doop.c 17 | @@ -1278,10 +1278,12 @@ Perl_do_kv(pTHX) 18 | SV *tmpstr; 19 | PUTBACK; 20 | tmpstr = hv_iterval(keys,entry); 21 | +#if 0 22 | DEBUG_H(Perl_sv_setpvf(aTHX_ tmpstr, "%lu%%%d=%lu", 23 | (unsigned long)HeHASH(entry), 24 | (int)HvMAX(keys)+1, 25 | (unsigned long)(HeHASH(entry) & HvMAX(keys)))); 26 | +#endif 27 | SPAGAIN; 28 | XPUSHs(tmpstr); 29 | } 30 | diff --git hv.c hv.c 31 | index ef686ab..514a8d0 100644 32 | --- hv.c 33 | +++ hv.c 34 | @@ -348,6 +348,9 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 35 | bool is_utf8; 36 | int masked_flags; 37 | const int return_svp = action & HV_FETCH_JUST_SV; 38 | +#ifdef DEBUGGING 39 | + unsigned int linear = 0; 40 | +#endif 41 | 42 | if (!hv) 43 | return NULL; 44 | @@ -634,6 +637,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 45 | entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)]; 46 | } 47 | for (; entry; entry = HeNEXT(entry)) { 48 | + DEBUG_H(linear++); 49 | if (HeHASH(entry) != hash) /* strings can't be equal */ 50 | continue; 51 | if (HeKLEN(entry) != (I32)klen) 52 | @@ -706,11 +710,17 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 53 | } 54 | if (flags & HVhek_FREEKEY) 55 | Safefree(key); 56 | + 57 | + /* fill, size, found index in collision list */ 58 | + DEBUG_H(PerlIO_printf(Perl_debug_log, "%lu\t%lu\t%u\n", HvKEYS(hv), HvMAX(hv), linear)); 59 | if (return_svp) { 60 | return entry ? (void *) &HeVAL(entry) : NULL; 61 | } 62 | return entry; 63 | } 64 | + 65 | + /* fill, size, not found, size of collision list */ 66 | + DEBUG_H(PerlIO_printf(Perl_debug_log, "%lu\t%lu\t%u -\n", HvKEYS(hv), HvMAX(hv), linear)); 67 | #ifdef DYNAMIC_ENV_FETCH /* %ENV lookup? If so, try to fetch the value now */ 68 | if (!(action & HV_FETCH_ISSTORE) 69 | && SvRMAGICAL((const SV *)hv) 70 | @@ -961,6 +971,9 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 71 | HE *const *first_entry; 72 | bool is_utf8 = (k_flags & HVhek_UTF8) ? TRUE : FALSE; 73 | int masked_flags; 74 | +#ifdef DEBUGGING 75 | + unsigned int linear = 0; 76 | +#endif 77 | 78 | if (SvRMAGICAL(hv)) { 79 | bool needs_copy; 80 | @@ -1041,6 +1054,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 81 | U8 mro_changes = 0; /* 1 = isa; 2 = package moved */ 82 | GV *gv = NULL; 83 | HV *stash = NULL; 84 | + DEBUG_H(linear++); 85 | 86 | if (HeHASH(entry) != hash) /* strings can't be equal */ 87 | continue; 88 | @@ -1061,6 +1075,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 89 | if (HeVAL(entry) == &PL_sv_placeholder) { 90 | if (k_flags & HVhek_FREEKEY) 91 | Safefree(key); 92 | + DEBUG_H(PerlIO_printf(Perl_debug_log, "%lu\t%lu\t%u DELpl\n", HvKEYS(hv), HvMAX(hv), linear)); 93 | return NULL; 94 | } 95 | if (SvREADONLY(hv) && HeVAL(entry) && SvREADONLY(HeVAL(entry))) { 96 | @@ -1149,6 +1164,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 97 | else if (mro_changes == 2) 98 | mro_package_moved(NULL, stash, gv, 1); 99 | 100 | + DEBUG_H(PerlIO_printf(Perl_debug_log, "%lu\t%lu\t%u DEL+\n", HvKEYS(hv), HvMAX(hv), linear)); 101 | return sv; 102 | } 103 | if (SvREADONLY(hv)) { 104 | @@ -1159,6 +1175,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, 105 | 106 | if (k_flags & HVhek_FREEKEY) 107 | Safefree(key); 108 | + DEBUG_H(PerlIO_printf(Perl_debug_log, "%lu\t%lu\t%u DEL-\n", HvKEYS(hv), HvMAX(hv), linear)); 109 | return NULL; 110 | } 111 | 112 | diff --git t/TEST t/TEST 113 | index 96eb6a4..e903da3 100755 114 | --- t/TEST 115 | +++ t/TEST 116 | @@ -251,7 +251,7 @@ sub _scan_test { 117 | test => $test, 118 | run_dir => $run_dir, 119 | return_dir => $return_dir, 120 | - testswitch => $testswitch, 121 | + testswitch => $testswitch.' -DH', 122 | utf8 => $utf8, 123 | file => $file_opts, 124 | switch => $switch, 125 | -- 126 | 1.9.1 127 | 128 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Artistic License 2.0 2 | 3 | Copyright (c) 2014 Reini Urban 4 | 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | This license establishes the terms under which a given free software 11 | Package may be copied, modified, distributed, and/or redistributed. 12 | The intent is that the Copyright Holder maintains some artistic 13 | control over the development of that Package while still keeping the 14 | Package available as open source and free software. 15 | 16 | You are always permitted to make arrangements wholly outside of this 17 | license directly with the Copyright Holder of a given Package. If the 18 | terms of this license do not permit the full use that you propose to 19 | make of the Package, you should contact the Copyright Holder and seek 20 | a different licensing arrangement. 21 | 22 | Definitions 23 | 24 | "Copyright Holder" means the individual(s) or organization(s) 25 | named in the copyright notice for the entire Package. 26 | 27 | "Contributor" means any party that has contributed code or other 28 | material to the Package, in accordance with the Copyright Holder's 29 | procedures. 30 | 31 | "You" and "your" means any person who would like to copy, 32 | distribute, or modify the Package. 33 | 34 | "Package" means the collection of files distributed by the 35 | Copyright Holder, and derivatives of that collection and/or of 36 | those files. A given Package may consist of either the Standard 37 | Version, or a Modified Version. 38 | 39 | "Distribute" means providing a copy of the Package or making it 40 | accessible to anyone else, or in the case of a company or 41 | organization, to others outside of your company or organization. 42 | 43 | "Distributor Fee" means any fee that you charge for Distributing 44 | this Package or providing support for this Package to another 45 | party. It does not mean licensing fees. 46 | 47 | "Standard Version" refers to the Package if it has not been 48 | modified, or has been modified only in ways explicitly requested 49 | by the Copyright Holder. 50 | 51 | "Modified Version" means the Package, if it has been changed, and 52 | such changes were not explicitly requested by the Copyright 53 | Holder. 54 | 55 | "Original License" means this Artistic License as Distributed with 56 | the Standard Version of the Package, in its current version or as 57 | it may be modified by The Perl Foundation in the future. 58 | 59 | "Source" form means the source code, documentation source, and 60 | configuration files for the Package. 61 | 62 | "Compiled" form means the compiled bytecode, object code, binary, 63 | or any other form resulting from mechanical transformation or 64 | translation of the Source form. 65 | 66 | 67 | Permission for Use and Modification Without Distribution 68 | 69 | (1) You are permitted to use the Standard Version and create and use 70 | Modified Versions for any purpose without restriction, provided that 71 | you do not Distribute the Modified Version. 72 | 73 | 74 | Permissions for Redistribution of the Standard Version 75 | 76 | (2) You may Distribute verbatim copies of the Source form of the 77 | Standard Version of this Package in any medium without restriction, 78 | either gratis or for a Distributor Fee, provided that you duplicate 79 | all of the original copyright notices and associated disclaimers. At 80 | your discretion, such verbatim copies may or may not include a 81 | Compiled form of the Package. 82 | 83 | (3) You may apply any bug fixes, portability changes, and other 84 | modifications made available from the Copyright Holder. The resulting 85 | Package will still be considered the Standard Version, and as such 86 | will be subject to the Original License. 87 | 88 | 89 | Distribution of Modified Versions of the Package as Source 90 | 91 | (4) You may Distribute your Modified Version as Source (either gratis 92 | or for a Distributor Fee, and with or without a Compiled form of the 93 | Modified Version) provided that you clearly document how it differs 94 | from the Standard Version, including, but not limited to, documenting 95 | any non-standard features, executables, or modules, and provided that 96 | you do at least ONE of the following: 97 | 98 | (a) make the Modified Version available to the Copyright Holder 99 | of the Standard Version, under the Original License, so that the 100 | Copyright Holder may include your modifications in the Standard 101 | Version. 102 | 103 | (b) ensure that installation of your Modified Version does not 104 | prevent the user installing or running the Standard Version. In 105 | addition, the Modified Version must bear a name that is different 106 | from the name of the Standard Version. 107 | 108 | (c) allow anyone who receives a copy of the Modified Version to 109 | make the Source form of the Modified Version available to others 110 | under 111 | 112 | (i) the Original License or 113 | 114 | (ii) a license that permits the licensee to freely copy, 115 | modify and redistribute the Modified Version using the same 116 | licensing terms that apply to the copy that the licensee 117 | received, and requires that the Source form of the Modified 118 | Version, and of any works derived from it, be made freely 119 | available in that license fees are prohibited but Distributor 120 | Fees are allowed. 121 | 122 | 123 | Distribution of Compiled Forms of the Standard Version 124 | or Modified Versions without the Source 125 | 126 | (5) You may Distribute Compiled forms of the Standard Version without 127 | the Source, provided that you include complete instructions on how to 128 | get the Source of the Standard Version. Such instructions must be 129 | valid at the time of your distribution. If these instructions, at any 130 | time while you are carrying out such distribution, become invalid, you 131 | must provide new instructions on demand or cease further distribution. 132 | If you provide valid instructions or cease distribution within thirty 133 | days after you become aware that the instructions are invalid, then 134 | you do not forfeit any of your rights under this license. 135 | 136 | (6) You may Distribute a Modified Version in Compiled form without 137 | the Source, provided that you comply with Section 4 with respect to 138 | the Source of the Modified Version. 139 | 140 | 141 | Aggregating or Linking the Package 142 | 143 | (7) You may aggregate the Package (either the Standard Version or 144 | Modified Version) with other packages and Distribute the resulting 145 | aggregation provided that you do not charge a licensing fee for the 146 | Package. Distributor Fees are permitted, and licensing fees for other 147 | components in the aggregation are permitted. The terms of this license 148 | apply to the use and Distribution of the Standard or Modified Versions 149 | as included in the aggregation. 150 | 151 | (8) You are permitted to link Modified and Standard Versions with 152 | other works, to embed the Package in a larger work of your own, or to 153 | build stand-alone binary or bytecode versions of applications that 154 | include the Package, and Distribute the result without restriction, 155 | provided the result does not expose a direct interface to the Package. 156 | 157 | 158 | Items That are Not Considered Part of a Modified Version 159 | 160 | (9) Works (including, but not limited to, modules and scripts) that 161 | merely extend or make use of the Package, do not, by themselves, cause 162 | the Package to be a Modified Version. In addition, such works are not 163 | considered parts of the Package itself, and are not subject to the 164 | terms of this license. 165 | 166 | 167 | General Provisions 168 | 169 | (10) Any use, modification, and distribution of the Standard or 170 | Modified Versions is governed by this Artistic License. By using, 171 | modifying or distributing the Package, you accept this license. Do not 172 | use, modify, or distribute the Package, if you do not accept this 173 | license. 174 | 175 | (11) If your Modified Version has been derived from a Modified 176 | Version made by someone other than you, you are nevertheless required 177 | to ensure that your Modified Version complies with the requirements of 178 | this license. 179 | 180 | (12) This license does not grant you the right to use any trademark, 181 | service mark, tradename, or logo of the Copyright Holder. 182 | 183 | (13) This license includes the non-exclusive, worldwide, 184 | free-of-charge patent license to make, have made, use, offer to sell, 185 | sell, import and otherwise transfer the Package with respect to any 186 | patent claims licensable by the Copyright Holder that are necessarily 187 | infringed by the Package. If you institute patent litigation 188 | (including a cross-claim or counterclaim) against any party alleging 189 | that the Package constitutes direct or contributory patent 190 | infringement, then this Artistic License to you shall terminate on the 191 | date that such litigation is filed. 192 | 193 | (14) Disclaimer of Warranty: 194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS 195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED 196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL 198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL 199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF 201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | perl-hash-stats 2 | =============== 3 | 4 | Counting the collisions with perl hash tables per function. 5 | (linear chaining in a linked list, subject to collision attacks) 6 | 7 | Average case (perl core testsuite) 8 | ---------------------------------- 9 | 10 | | Hash Function | collisions| time[sec] | Quality | cyc/hash | 11 | |:--------------|----------:|-----------:|---------|---------:| 12 | | FNV1A | 0.862 | 535 sec | BAD | 33.19 | 13 | | OOAT_OLD | 0.861 | 537 sec | BAD | 50.83 | 14 | | CRC32 | 0.841 | 538 sec | INSECURE| 31.27 | 15 | | SUPERFAST | 0.848 | 537 sec | BAD | 27.75 | 16 | | SDBM | 0.874 | 541 sec | BAD | 29.23 | 17 | | SPOOKY32 | 0.813 | 546 sec | GOOD | 38.45 | 18 | | MURMUR64A | 0.855 | 546 sec | BAD | 28.80 | 19 | | MURMUR64B | 0.857 | 546 sec | BAD | 27.48 | 20 | | OOAT_HARD | 0.842 | 547 sec | BAD | 61.03 | 21 | | MURMUR3 | 0.883 | 547 sec | GOOD | 29.54 | 22 | | DJB2 | 0.898 | 547 sec | BAD | 33.78 | 23 | | METRO64 | 0.892 | 550 sec | GOOD | 26.78 | 24 | | OOAT | 0.860 | 551 sec | BAD | ?? | 25 | | SIPHASH | 0.853 | 551 sec | GOOD | 114.48 | 26 | | METRO64CRC | 0.872 | 559 sec | GOOD | 23.27 | 27 | 28 | Less collisions are better, less time is faster. 29 | A hash table lookup consists of one constant hash function 30 | (depending only on the length of the key) and then resolving 31 | 0-x collisions (in our avg case 0-10). 32 | 33 | **Speed:** Note that hash table speed measured here is a combination 34 | of code-size, less code - better icache, CPU (cyc/hash) and less 35 | collisions (better quality, less work). But we only measured the 36 | primitive linked list implementation with 100% fill rate yet, which 37 | has to chase linked list pointers and looses the data cache, unlike 38 | with open-addressing. 39 | 40 | **FNV1a** is the current leader. Even if it creates more collisions 41 | than a good hash, and is not as fast in bulk as others, it is smaller 42 | and faster when being used inlined in hash table functions. Confirmed with 43 | testing the [sanmayce](http://www.sanmayce.com/Fastest_Hash/) bigger 44 | and unrolled variant. 45 | 46 | **Spooky32**, Bob Jenkins' latest creation, creates the least 47 | collisions by far and is the fastest of the good hash functions here, 48 | but only works on 64 bit machines. **Murmur3** interestingly creates a 49 | lot of collisions, even more than the simple old OOAT variants. 50 | 51 | The individually fastest hash function, which should be used for 52 | checksumming larger files, **METRO**, does not perform good as hash 53 | table function at all. It has too much code and it is not optimized 54 | to avoid collisions with ASCII text keys. 55 | 56 | The short perl5 testsuite (op,base,perf) has a key size of median = 57 | 33, and avg of 83. The most commonly used key sizes are 4, 101 and 58 | 2, the most common hash tables sizes are 7, 255 and 31. 59 | 60 | A hash table size of 7 uses the last 3 bits of the hash function result, 61 | 63 uses only 6 bits of 32 and 127 uses 7 bits. 62 | 63 | * collisions are the number of linked list iterations per hash table usage. 64 | * quality and cycles/hash is measured with [smhasher](https://github.com/rurban/smhasher) 65 | 66 | Hash table sizes 67 | ---------------- 68 | 69 | | size | count | 70 | |:-----:|----------:| 71 | | 0 | 2403 | 72 | | 1 | 383 | 73 | | 3 | 434 | 74 | | 7 | 30816359 | 75 | | 15 | 19761019 | 76 | | 31 | 20566188 | 77 | | 63 | 30131283 | 78 | | 127 | 28054277 | 79 | | 255 | 15104276 | 80 | | 511 | 7146648 | 81 | | 1023 | 3701004 | 82 | | 2047 | 1015462 | 83 | | 4095 | 217107 | 84 | | 8191 | 284997 | 85 | | 16383 | 237284 | 86 | | 32767 | 169823 | 87 | 88 | Note that perl ony supports int32 (32bit) sized tables, not 64bit arrays. 89 | Larger keysets need to be tied to bigger key-value stores, such as 90 | [LMDB_File](http://search.cpan.org/dist/LMDB_File/) or at least 91 | AnyDBM_File, otherwise you'll get a hell lot of collisions. 92 | 93 | It should be studied of leaving out one or two sizes and therefore the costly 94 | rehashing is worthwile. Good candidates for this dataset to skip seem to be 95 | 15 and 63. 96 | 97 | For double hashing perl5 need to use prime number sized hash tables to 98 | make the 2nd hash function work. For 32bit the primes can be stored 99 | in a constant table as in glibc. 100 | 101 | 102 | Number of collisions with CRC32 103 | ------------------------------ 104 | CRC32 is a good and fast hash function, on SSE4 intel processors or 105 | armv7 and armv8 it costs just a few cycles, but unfortunately too trivial 106 | to create collisions when allowing binary keys, the worst case. 107 | 108 | 109 | | collisions| count | 110 | |:---------:|----------:| 111 | | 0 | 26176163 | 112 | | 1 | 100979326 | 113 | | 2 | 25745874 | 114 | | 3 | 4526405 | 115 | | 4 | 512177 | 116 | | 5 | 46749 | 117 | | 6 | 4015 | 118 | | 7 | 187 | 119 | | 8 | 8 | 120 | 121 | Note that 0 collisions can occur with an early return in the hash 122 | table lookup function, such as with empty hash tables. 123 | The number of collisions is independent of the hash table size or key length. 124 | It depends on the fill factor, the quality of the hash function and the key. 125 | 126 | This is the average case. Worst cases can be produced by guessing the random hash 127 | seed from leakage of sorting order (unsorted keys in JSON, YAML, RSS interfaces, or such), 128 | (_or even fooling with the ENV or process memory_), and then creating colliding keys, which 129 | would lead to exponential time DOS attacks with linear time attack costs. [RT #22371](https://rt.perl.org/Public/Bug/Display.html?id=22371) and ["Denial of Service via Algorithmic Complexity Attacks", S Crosby, D Wallach, Rice 1993](http://www.rootsecure.net/content/downloads/pdf/dos_via_algorithmic_complexity_attack.pdf). 130 | Long running perl processes with publicly exposed sorting order and input acceptance of hash keys 131 | should really be avoided without proper countermeasures. PHP e.g. does MAX\_POST\_SIZE. 132 | How to get the private random seed is e.g. described in ["REMOTE ALGORITHMIC COMPLEXITY ATTACKS AGAINST 133 | RANDOMIZED HASH TABLES", N Bar-Yosef, A Wool - 2009 - Springer](https://www.eng.tau.ac.il/~yash/C2_039_Wool.pdf). 134 | 135 | Perl and similar dynamic languages really need to improve their collision algorithm, and choose 136 | a combination of fast and good enough hash function. None of this is currently implemented in 137 | standard SW besides Kyoto DB, though Knuth proposed to use sorted buckets 138 | ["Ordered hash tables", O Amble, D Knuth 1973](http://comjnl.oxfordjournals.org/content/17/2/135.full.pdf). 139 | Most technical papers accept degeneration into linear search for bucket collisions as is. 140 | Notably e.g. even the Linux kernel [F. Weimer, “Algorithmic complexity attacks and the 141 | linux networking code”, May 2003](http://www.enyo.de/fw/security/notes/linux-dst-cache-dos.html), 142 | though glibc, gcc and libliberty and others switched to open addressing with double hashing recently, 143 | where collisions just trigger hash table resizes, and the choice of the 2nd function will reduce 144 | collisions dramatically. 145 | DJB's DNS server has an explicit check for "hash flooding" attempts. 146 | Some rare hash tables implementations use rb-trees. 147 | 148 | For City there currently exists a simple universal C function to 149 | easily create collisions per seed. crc32 is exploitable even more 150 | easily. Note that this exists for every hash function, just encode 151 | your hash SAT solver-friendly and look at the generated model. It is 152 | even incredibly simple if you calculate only the needed last bits 153 | dependent on the hash table size (8-15 bits). So striking out city 154 | for such security claims does not hold. The most secure hash function 155 | can be attacked this way. Any practical attacker has enough time in 156 | advance to create enough colliding keys dependent only on the random 157 | seed, and can easily verify it by time measurements. The code is just 158 | not out yet, and the costs for some slower (cryptographically secure) 159 | hash functions might be too high. But people already encoded SHA-2 160 | into SMTLIB code to attack bitcoin, and high-level frameworks such as 161 | frama-c, klee or z3 are becoming increasingly popular. 162 | 163 | crc-32c, the Castagnoli variant used in new hardware, is recommended 164 | by 165 | [xcore Tip & Tricks: Hash Tables](http://xcore.github.io/doc_tips_and_tricks/hash-tables.html) 166 | and also analysed by 167 | [Bob Jenkin](http://burtleburtle.net/bob/hash/examhash.html). 168 | 169 | cachegrind cost model 170 | --------------------- 171 | 172 | Instead of costly benchmarking, we can count the instructions via cachegrind. 173 | Thanks to davem for this trick. 174 | 175 | We create miniperl's for all our hash funcs. I've add a new `Configure -Dhash_func=$h` config variable for this, but a `-DPERL_HASH_FUNC_$h` is also enough. 176 | 177 | for m in miniperl-*; do 178 | echo $m; 179 | valgrind --tool=cachegrind ./$m -e'my %h=("foo"=>1);$h{foo} for 0..100' 2>&1 | \ 180 | egrep 'rate|refs|misses'; 181 | done 182 | 183 | And we write a [simple script](https://github.com/rurban/perl-hash-stats/blob/master/cachegrind-cost.pl) to apply the cost functions for various 184 | Lx cache misses. cachegrind can only do the first and last cache line, 185 | so we count 10 insn for a L1 (_first line_) miss, and 200 insn for a 186 | LL (_last line_) miss. 187 | The baseline `-e0` is 12774328. 188 | 189 | $ valgrind --tool=cachegrind /usr/src/perl/blead/cperl/miniperl -e0 2>&1 |\ 190 | egrep 'rate|refs|misses' |\ 191 | ./cachegrind-cost.pl 192 | 12774328 193 | 194 | $ ./cachegrind-cost.pl log.hash-speed |\ 195 | sort -nk2 -t$'\t'| \ 196 | awk '{print $1 "\t", $2 - 12774328}' 197 | 198 | | hash |cost [insn]| notes | 199 | |------------|--------:|--------------| 200 | | CRC32 | 10125 | modern CPU only, insecure | 201 | | FNV1A | 20988 | bad | 202 | | FNV1A\_YT | 53973 | bad | 203 | | SDBM | 64917 | bad | 204 | | MURMUR64A | 64971 | 64-bit only | 205 | | MURMUR64B | 67044 | bad | 206 | | DJB2 | 73644 | bad | 207 | | METRO64CRC | 73941 | modern CPU only | 208 | | METRO64 | 74510 | 64-bit only | 209 | | SUPERFAST | 83053 | bad | 210 | | OAAT_OLD | 95318 | bad | 211 | | MURMUR3 | 95774 | | 212 | | OOAT | 96407 | bad | 213 | | SPOOKY32 | 110398 | 64-bit only | 214 | | OOAT_HARD | 127221 | bad | 215 | | SIPHASH | 140713 | | 216 | 217 | Fill rates 218 | ---------- 219 | 220 | Below are graphs testing the fill rates from 50% up to 100%, which 221 | is the current default. The usual fill rate is 80-100%, 50% for open 222 | addressing, and up to 97% for very good hash functions, like CRC32 223 | or Spooky32. 224 | 225 | Currently tested is only the default and slow 226 | `PERL_PERTURB_KEYS_RANDOM` strategy, not the other strategies 227 | `PERL_PERTURB_KEYS_DISABLED`, `PERL_PERTURB_KEYS_DETERMINISTIC` and my 228 | `new PERL_PERTURB_KEYS_TOP` to move every found bucket to the top, the 229 | usually fastest strategy for linked lists. 230 | 231 | ![OOTA_HARD](hash-fillrate-def-OOAT_HARD.png) 232 | 233 | ![FNV1A](hash-fillrate-def-FNV1A.png) 234 | 235 | See also 236 | -------- 237 | 238 | * See [blogs.perl.org: statistics-for-perl-hash-tables](http://blogs.perl.org/users/rurban/2014/04/statistics-for-perl-hash-tables.html) for a more detailled earlier description, and 239 | 240 | * [Emmanuel Goossaert's blog](http://codecapsule.com/2013/05/13/implementing-a-key-value-store-part-5-hash-table-implementations/) compares some hash table implementations and esp. collision handling for efficiency, not security. 241 | 242 | * See [smhasher](https://github.com/rurban/smhasher) for performance and quality tests 243 | of most known hash functions. 244 | 245 | * See [Perfect::Hash](https://github.com/rurban/Perfect-Hash) for benchmarks and 246 | implementations of **perfect hashes**, i.e. fast lookup in readonly stringmaps. 247 | 248 | * _hash.stats_ for the distribution of the collisions 249 | 250 | * _hash.result.*_ for the table sizes 251 | -------------------------------------------------------------------------------- /log.hash-speed: -------------------------------------------------------------------------------- 1 | miniperl-CRC32 2 | ==34196== I refs: 12,722,475 3 | ==34196== I1 misses: 11,440 4 | ==34196== LLi misses: 5,438 5 | ==34196== I1 miss rate: 0.09% 6 | ==34196== LLi miss rate: 0.04% 7 | ==34196== D refs: 3,586,572 (2,647,622 rd + 938,950 wr) 8 | ==34196== D1 misses: 38,326 ( 32,463 rd + 5,863 wr) 9 | ==34196== LLd misses: 11,992 ( 7,907 rd + 4,085 wr) 10 | ==34196== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 11 | ==34196== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 12 | ==34196== LL refs: 49,766 ( 43,903 rd + 5,863 wr) 13 | ==34196== LL misses: 17,430 ( 13,345 rd + 4,085 wr) 14 | ==34196== LL miss rate: 0.1% ( 0.1% + 0.4% ) 15 | miniperl-DJB2 16 | ==34198== I refs: 12,786,353 17 | ==34198== I1 misses: 11,318 18 | ==34198== LLi misses: 5,454 19 | ==34198== I1 miss rate: 0.09% 20 | ==34198== LLi miss rate: 0.04% 21 | ==34198== D refs: 3,603,771 (2,660,301 rd + 943,470 wr) 22 | ==34198== D1 misses: 38,129 ( 32,243 rd + 5,886 wr) 23 | ==34198== LLd misses: 11,952 ( 7,882 rd + 4,070 wr) 24 | ==34198== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 25 | ==34198== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 26 | ==34198== LL refs: 49,447 ( 43,561 rd + 5,886 wr) 27 | ==34198== LL misses: 17,406 ( 13,336 rd + 4,070 wr) 28 | ==34198== LL miss rate: 0.1% ( 0.1% + 0.4% ) 29 | miniperl-FNV1A 30 | ==34200== I refs: 12,733,695 31 | ==34200== I1 misses: 11,261 32 | ==34200== LLi misses: 5,456 33 | ==34200== I1 miss rate: 0.09% 34 | ==34200== LLi miss rate: 0.04% 35 | ==34200== D refs: 3,588,694 (2,649,882 rd + 938,812 wr) 36 | ==34200== D1 misses: 38,108 ( 32,244 rd + 5,864 wr) 37 | ==34200== LLd misses: 12,032 ( 7,907 rd + 4,125 wr) 38 | ==34200== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 39 | ==34200== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 40 | ==34200== LL refs: 49,369 ( 43,505 rd + 5,864 wr) 41 | ==34200== LL misses: 17,488 ( 13,363 rd + 4,125 wr) 42 | ==34200== LL miss rate: 0.1% ( 0.1% + 0.4% ) 43 | miniperl-FNV1A_YT 44 | ==34202== I refs: 12,766,906 45 | ==34202== I1 misses: 11,170 46 | ==34202== LLi misses: 5,496 47 | ==34202== I1 miss rate: 0.09% 48 | ==34202== LLi miss rate: 0.04% 49 | ==34202== D refs: 3,602,183 (2,657,875 rd + 944,308 wr) 50 | ==34202== D1 misses: 37,991 ( 32,082 rd + 5,909 wr) 51 | ==34202== LLd misses: 12,014 ( 7,873 rd + 4,141 wr) 52 | ==34202== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 53 | ==34202== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 54 | ==34202== LL refs: 49,161 ( 43,252 rd + 5,909 wr) 55 | ==34202== LL misses: 17,510 ( 13,369 rd + 4,141 wr) 56 | ==34202== LL miss rate: 0.1% ( 0.1% + 0.4% ) 57 | miniperl-METRO64 58 | ==34204== I refs: 12,786,883 59 | ==34204== I1 misses: 11,468 60 | ==34204== LLi misses: 5,490 61 | ==34204== I1 miss rate: 0.09% 62 | ==34204== LLi miss rate: 0.04% 63 | ==34204== D refs: 3,611,312 (2,663,798 rd + 947,514 wr) 64 | ==34204== D1 misses: 38,253 ( 32,285 rd + 5,968 wr) 65 | ==34204== LLd misses: 12,014 ( 7,877 rd + 4,137 wr) 66 | ==34204== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 67 | ==34204== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 68 | ==34204== LL refs: 49,721 ( 43,753 rd + 5,968 wr) 69 | ==34204== LL misses: 17,504 ( 13,367 rd + 4,137 wr) 70 | ==34204== LL miss rate: 0.1% ( 0.1% + 0.4% ) 71 | miniperl-METRO64CRC 72 | ==34206== I refs: 12,785,883 73 | ==34206== I1 misses: 11,806 74 | ==34206== LLi misses: 5,495 75 | ==34206== I1 miss rate: 0.09% 76 | ==34206== LLi miss rate: 0.04% 77 | ==34206== D refs: 3,608,439 (2,661,417 rd + 947,022 wr) 78 | ==34206== D1 misses: 38,359 ( 32,338 rd + 6,021 wr) 79 | ==34206== LLd misses: 12,001 ( 7,904 rd + 4,097 wr) 80 | ==34206== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 81 | ==34206== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 82 | ==34206== LL refs: 50,165 ( 44,144 rd + 6,021 wr) 83 | ==34206== LL misses: 17,496 ( 13,399 rd + 4,097 wr) 84 | ==34206== LL miss rate: 0.1% ( 0.1% + 0.4% ) 85 | miniperl-MURMUR3 86 | ==34208== I refs: 12,807,464 87 | ==34208== I1 misses: 11,885 88 | ==34208== LLi misses: 5,551 89 | ==34208== I1 miss rate: 0.09% 90 | ==34208== LLi miss rate: 0.04% 91 | ==34208== D refs: 3,606,771 (2,661,735 rd + 945,036 wr) 92 | ==34208== D1 misses: 38,523 ( 32,611 rd + 5,912 wr) 93 | ==34208== LLd misses: 12,010 ( 7,913 rd + 4,097 wr) 94 | ==34208== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 95 | ==34208== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 96 | ==34208== LL refs: 50,408 ( 44,496 rd + 5,912 wr) 97 | ==34208== LL misses: 17,561 ( 13,464 rd + 4,097 wr) 98 | ==34208== LL miss rate: 0.1% ( 0.1% + 0.4% ) 99 | miniperl-MURMUR_HASH_64A 100 | ==34210== I refs: 12,776,903 101 | ==34210== I1 misses: 11,406 102 | ==34210== LLi misses: 5,514 103 | ==34210== I1 miss rate: 0.09% 104 | ==34210== LLi miss rate: 0.04% 105 | ==34210== D refs: 3,605,152 (2,660,425 rd + 944,727 wr) 106 | ==34210== D1 misses: 38,791 ( 32,865 rd + 5,926 wr) 107 | ==34210== LLd misses: 11,979 ( 7,909 rd + 4,070 wr) 108 | ==34210== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 109 | ==34210== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 110 | ==34210== LL refs: 50,197 ( 44,271 rd + 5,926 wr) 111 | ==34210== LL misses: 17,493 ( 13,423 rd + 4,070 wr) 112 | ==34210== LL miss rate: 0.1% ( 0.1% + 0.4% ) 113 | miniperl-MURMUR_HASH_64B 114 | ==34212== I refs: 12,779,009 115 | ==34212== I1 misses: 11,388 116 | ==34212== LLi misses: 5,485 117 | ==34212== I1 miss rate: 0.09% 118 | ==34212== LLi miss rate: 0.04% 119 | ==34212== D refs: 3,605,049 (2,659,993 rd + 945,056 wr) 120 | ==34212== D1 misses: 38,696 ( 32,734 rd + 5,962 wr) 121 | ==34212== LLd misses: 12,059 ( 7,867 rd + 4,192 wr) 122 | ==34212== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 123 | ==34212== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 124 | ==34212== LL refs: 50,084 ( 44,122 rd + 5,962 wr) 125 | ==34212== LL misses: 17,544 ( 13,352 rd + 4,192 wr) 126 | ==34212== LL miss rate: 0.1% ( 0.1% + 0.4% ) 127 | miniperl-ONE_AT_A_TIME 128 | ==34214== I refs: 12,808,587 129 | ==34214== I1 misses: 11,174 130 | ==34214== LLi misses: 5,447 131 | ==34214== I1 miss rate: 0.09% 132 | ==34214== LLi miss rate: 0.04% 133 | ==34214== D refs: 3,604,221 (2,660,561 rd + 943,660 wr) 134 | ==34214== D1 misses: 38,755 ( 32,789 rd + 5,966 wr) 135 | ==34214== LLd misses: 11,999 ( 7,874 rd + 4,125 wr) 136 | ==34214== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 137 | ==34214== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 138 | ==34214== LL refs: 49,929 ( 43,963 rd + 5,966 wr) 139 | ==34214== LL misses: 17,446 ( 13,321 rd + 4,125 wr) 140 | ==34214== LL miss rate: 0.1% ( 0.1% + 0.4% ) 141 | miniperl-ONE_AT_A_TIME_HARD 142 | ==34216== I refs: 12,839,632 143 | ==34216== I1 misses: 11,005 144 | ==34216== LLi misses: 5,472 145 | ==34216== I1 miss rate: 0.09% 146 | ==34216== LLi miss rate: 0.04% 147 | ==34216== D refs: 3,608,516 (2,664,372 rd + 944,144 wr) 148 | ==34216== D1 misses: 38,636 ( 32,666 rd + 5,970 wr) 149 | ==34216== LLd misses: 12,056 ( 7,899 rd + 4,157 wr) 150 | ==34216== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 151 | ==34216== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 152 | ==34216== LL refs: 49,641 ( 43,671 rd + 5,970 wr) 153 | ==34216== LL misses: 17,528 ( 13,371 rd + 4,157 wr) 154 | ==34216== LL miss rate: 0.1% ( 0.1% + 0.4% ) 155 | miniperl-ONE_AT_A_TIME_OLD 156 | ==34219== I refs: 12,807,178 157 | ==34219== I1 misses: 11,510 158 | ==34219== LLi misses: 5,460 159 | ==34219== I1 miss rate: 0.09% 160 | ==34219== LLi miss rate: 0.04% 161 | ==34219== D refs: 3,603,657 (2,660,158 rd + 943,499 wr) 162 | ==34219== D1 misses: 38,737 ( 32,762 rd + 5,975 wr) 163 | ==34219== LLd misses: 12,001 ( 7,873 rd + 4,128 wr) 164 | ==34219== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 165 | ==34219== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 166 | ==34219== LL refs: 50,247 ( 44,272 rd + 5,975 wr) 167 | ==34219== LL misses: 17,461 ( 13,333 rd + 4,128 wr) 168 | ==34219== LL miss rate: 0.1% ( 0.1% + 0.4% ) 169 | miniperl-SDBM 170 | ==34221== I refs: 12,777,304 171 | ==34221== I1 misses: 11,361 172 | ==34221== LLi misses: 5,450 173 | ==34221== I1 miss rate: 0.09% 174 | ==34221== LLi miss rate: 0.04% 175 | ==34221== D refs: 3,604,050 (2,660,388 rd + 943,662 wr) 176 | ==34221== D1 misses: 38,401 ( 32,508 rd + 5,893 wr) 177 | ==34221== LLd misses: 11,959 ( 7,910 rd + 4,049 wr) 178 | ==34221== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 179 | ==34221== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 180 | ==34221== LL refs: 49,762 ( 43,869 rd + 5,893 wr) 181 | ==34221== LL misses: 17,409 ( 13,360 rd + 4,049 wr) 182 | ==34221== LL miss rate: 0.1% ( 0.1% + 0.4% ) 183 | miniperl-SIPHASH 184 | ==34223== I refs: 12,852,290 185 | ==34223== I1 misses: 11,512 186 | ==34223== LLi misses: 5,507 187 | ==34223== I1 miss rate: 0.09% 188 | ==34223== LLi miss rate: 0.04% 189 | ==34223== D refs: 3,609,035 (2,663,573 rd + 945,462 wr) 190 | ==34223== D1 misses: 38,923 ( 32,898 rd + 6,025 wr) 191 | ==34223== LLd misses: 12,096 ( 7,912 rd + 4,184 wr) 192 | ==34223== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 193 | ==34223== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 194 | ==34223== LL refs: 50,435 ( 44,410 rd + 6,025 wr) 195 | ==34223== LL misses: 17,603 ( 13,419 rd + 4,184 wr) 196 | ==34223== LL miss rate: 0.1% ( 0.1% + 0.4% ) 197 | miniperl-SPOOKY32 198 | ==34226== I refs: 12,821,958 199 | ==34226== I1 misses: 11,556 200 | ==34226== LLi misses: 5,537 201 | ==34226== I1 miss rate: 0.09% 202 | ==34226== LLi miss rate: 0.04% 203 | ==34226== D refs: 3,617,947 (2,667,139 rd + 950,808 wr) 204 | ==34226== D1 misses: 38,926 ( 32,892 rd + 6,034 wr) 205 | ==34226== LLd misses: 12,066 ( 7,888 rd + 4,178 wr) 206 | ==34226== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 207 | ==34226== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 208 | ==34226== LL refs: 50,482 ( 44,448 rd + 6,034 wr) 209 | ==34226== LL misses: 17,603 ( 13,425 rd + 4,178 wr) 210 | ==34226== LL miss rate: 0.1% ( 0.1% + 0.4% ) 211 | miniperl-SUPERFAST 212 | ==34228== I refs: 12,795,312 213 | ==34228== I1 misses: 11,352 214 | ==34228== LLi misses: 5,497 215 | ==34228== I1 miss rate: 0.09% 216 | ==34228== LLi miss rate: 0.04% 217 | ==34228== D refs: 3,606,048 (2,661,459 rd + 944,589 wr) 218 | ==34228== D1 misses: 38,513 ( 32,554 rd + 5,959 wr) 219 | ==34228== LLd misses: 11,984 ( 7,877 rd + 4,107 wr) 220 | ==34228== D1 miss rate: 1.1% ( 1.2% + 0.6% ) 221 | ==34228== LLd miss rate: 0.3% ( 0.3% + 0.4% ) 222 | ==34228== LL refs: 49,865 ( 43,906 rd + 5,959 wr) 223 | ==34228== LL misses: 17,481 ( 13,374 rd + 4,107 wr) 224 | ==34228== LL miss rate: 0.1% ( 0.1% + 0.4% ) 225 | --------------------------------------------------------------------------------