mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 14:51:11 +01:00
Fix SipHash-2-4 performance for non multiple of 8 buffers.
Code cribbed from Andrew Moon's Public Domain SipHash-2-4 implementation (which IMO is also cleaner). Fixes bug 17544.
This commit is contained in:
parent
5a37061885
commit
b71f6d6a47
2 changed files with 24 additions and 37 deletions
4
changes/bug17544
Normal file
4
changes/bug17544
Normal file
|
@ -0,0 +1,4 @@
|
|||
o Minor bugfix (SipHash-2-4 performance):
|
||||
- Improve performance when hashing non-multiple of 8 sized buffers,
|
||||
based on Andrew Moon's Public Domain SipHash-2-4 implementation.
|
||||
Fixes bug 17544; bugfix on 0.2.5.3-alpha.
|
|
@ -97,65 +97,48 @@
|
|||
#endif
|
||||
|
||||
uint64_t siphash24(const void *src, unsigned long src_sz, const struct sipkey *key) {
|
||||
const uint8_t *m = src;
|
||||
uint64_t k0 = key->k0;
|
||||
uint64_t k1 = key->k1;
|
||||
uint64_t b = (uint64_t)src_sz << 56;
|
||||
#ifdef UNALIGNED_OK
|
||||
const uint64_t *in = (uint64_t*)src;
|
||||
#else
|
||||
/* On platforms where alignment matters, if 'in' is a pointer to a
|
||||
* datatype that must be aligned, the compiler is allowed to
|
||||
* generate code that assumes that it is aligned as such.
|
||||
*/
|
||||
const uint8_t *in = (uint8_t *)src;
|
||||
#endif
|
||||
|
||||
uint64_t t;
|
||||
uint8_t *pt, *m;
|
||||
uint64_t last7 = (uint64_t)(src_sz & 0xff) << 56;
|
||||
size_t i, blocks;
|
||||
|
||||
uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
|
||||
uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
|
||||
uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
|
||||
uint64_t v3 = k1 ^ 0x7465646279746573ULL;
|
||||
|
||||
while (src_sz >= 8) {
|
||||
for (i = 0, blocks = (src_sz & ~7); i < blocks; i+= 8) {
|
||||
#ifdef UNALIGNED_OK
|
||||
uint64_t mi = _le64toh(*in);
|
||||
in += 1;
|
||||
uint64_t mi = _le64toh(*(m + i));
|
||||
#else
|
||||
uint64_t mi;
|
||||
memcpy(&mi, in, 8);
|
||||
memcpy(&mi, m + i, 8);
|
||||
mi = _le64toh(mi);
|
||||
in += 8;
|
||||
#endif
|
||||
src_sz -= 8;
|
||||
v3 ^= mi;
|
||||
DOUBLE_ROUND(v0,v1,v2,v3);
|
||||
v0 ^= mi;
|
||||
}
|
||||
|
||||
t = 0; pt = (uint8_t*)&t; m = (uint8_t*)in;
|
||||
switch (src_sz) {
|
||||
case 7: pt[6] = m[6];
|
||||
case 6: pt[5] = m[5];
|
||||
case 5: pt[4] = m[4];
|
||||
#ifdef UNALIGNED_OK
|
||||
case 4: *((uint32_t*)&pt[0]) = *((uint32_t*)&m[0]); break;
|
||||
#else
|
||||
case 4: pt[3] = m[3];
|
||||
#endif
|
||||
case 3: pt[2] = m[2];
|
||||
case 2: pt[1] = m[1];
|
||||
case 1: pt[0] = m[0];
|
||||
switch (src_sz - blocks) {
|
||||
case 7: last7 |= (uint64_t)m[i + 6] << 48;
|
||||
case 6: last7 |= (uint64_t)m[i + 5] << 40;
|
||||
case 5: last7 |= (uint64_t)m[i + 4] << 32;
|
||||
case 4: last7 |= (uint64_t)m[i + 3] << 24;
|
||||
case 3: last7 |= (uint64_t)m[i + 2] << 16;
|
||||
case 2: last7 |= (uint64_t)m[i + 1] << 8;
|
||||
case 1: last7 |= (uint64_t)m[i + 0] ;
|
||||
case 0:
|
||||
default:;
|
||||
}
|
||||
b |= _le64toh(t);
|
||||
|
||||
v3 ^= b;
|
||||
v3 ^= last7;
|
||||
DOUBLE_ROUND(v0,v1,v2,v3);
|
||||
v0 ^= b; v2 ^= 0xff;
|
||||
v0 ^= last7;
|
||||
v2 ^= 0xff;
|
||||
DOUBLE_ROUND(v0,v1,v2,v3);
|
||||
DOUBLE_ROUND(v0,v1,v2,v3);
|
||||
return (v0 ^ v1) ^ (v2 ^ v3);
|
||||
return v0 ^ v1 ^ v2 ^ v3;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue