X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/8e5745a278c26c77815324a703181935e7b26dc4..b1a20beee623c83315c3ce21abc7bcce103c6efb:/hash/t/hash-test.c?ds=inline diff --git a/hash/t/hash-test.c b/hash/t/hash-test.c index 57a6ce8..f587c30 100644 --- a/hash/t/hash-test.c +++ b/hash/t/hash-test.c @@ -27,19 +27,59 @@ /*----- Header files ------------------------------------------------------*/ +#include "tvec.h" +#include "tvec-bench.h" +#include "tvec-types.h" + #include "crc32.h" +#include "siphash.h" #include "unihash.h" -#include "tvec.h" -/*----- Main code ---------------------------------------------------------*/ +/*----- Register allocation -----------------------------------------------*/ enum { RH, NROUT, RK = NROUT, RM, NREG }; +/*----- Testing utilities -------------------------------------------------*/ + struct step { size_t s; }; +static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx) +{ + static const size_t steps[] = { 1, 5, 6, 7, 8, 23 }; + struct step step; + size_t i; + + fn(tv->in, tv->out, 0); + tvec_check(tv, "whole buffer"); + + for (i = 0; i < N(steps); i++) { + step.s = steps[i]; + fn(tv->in, tv->out, &step); + tvec_check(tv, "step = %lu", (unsigned long)steps[i]); + } +} + +static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 }; + +static void before_hash(struct tvec_state *tv, void *ctx) + { tvec_allocbuffer(&tv->in[RM].v); } + +/*----- CRC32 -------------------------------------------------------------*/ + +static const struct tvec_regdef bench_regs[] = { + { "msz", &tvty_buffer, RM, TVRF_ID }, + TVEC_ENDREGS +}; + +static const struct tvec_regdef crc32_regs[] = { + { "m", &tvty_bytes, RM, 0 }, + { "h", &tvty_uint, RH, 0, { &tvrange_u32 } }, + TVEC_ENDREGS +}; + static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out, void *ctx) { @@ -56,59 +96,77 @@ static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out, } } -static void before_hash(struct tvec_state *tv, void *ctx) - { tvec_allocbuffer(&tv->in[RM].v); } +static const struct tvec_test crc32_test = + { "crc32", crc32_regs, &step_testenv, test_crc32 }; static void bench_crc32(const struct tvec_reg *in, struct tvec_reg *out, void *ctx) { crc32(0, in[RM].v.bytes.p, in[RM].v.bytes.sz); } + static const struct tvec_env crc32_benchenv = { 0, 0, 0, before_hash }; +static const struct tvec_benchenv crc32_bench = + { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv }; +static const struct tvec_test crc32_benchtest = + { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 }; -static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out, +/*----- SipHash -----------------------------------------------------------*/ + +static const struct tvec_urange + siphash_keyrange = { SIPHASH_KEYSZ, SIPHASH_KEYSZ }, + siphash_hashrange = { 8, 8 }; + +static const struct tvec_regdef siphash_regs[] = { + { "k", &tvty_bytes, RK, 0, { &siphash_keyrange } }, + { "m", &tvty_bytes, RM, 0 }, + { "h", &tvty_bytes, RH, 0, { &siphash_hashrange } }, + TVEC_ENDREGS +}; + +static void test_siphash(const struct tvec_reg *in, struct tvec_reg *out, void *ctx) { const struct step *step = ctx; - unihash_info ui; const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz; - uint32 h; + struct siphash_key k; + struct siphash s; + kludge64 h; - unihash_setkey(&ui, in[RK].v.u); + siphash_setkey(&k, in[RK].v.bytes.p); if (!step) - out[RH].v.u = unihash(&ui, p, sz); + h = siphash(&k, p, sz); else { - for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s) - h = unihash_hash(&ui, h, p, step->s); - out[RH].v.u = unihash_hash(&ui, h, p, sz); + siphash_init(&s, &k); + for (; sz > step->s; p += step->s, sz -= step->s) + siphash_hash(&s, p, step->s); + siphash_hash(&s, p, sz); + h = siphash_done(&s); } + tvec_allocbytes(&out[RH].v, 8); STORE64_L_(out[RH].v.bytes.p, h); } -static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out, - void *ctx) - { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); } -static void setup_unihash(struct tvec_state *tv, - const struct tvec_env *env, void *pctx, void *ctx) - { tvec_allocbuffer(&tv->in[RM].v); unihash_setkey(ctx, 0); } -static const struct tvec_env unihash_benchenv = - { sizeof(unihash_info), setup_unihash, 0, before_hash }; +static const struct tvec_test siphash_test = + { "siphash", siphash_regs, &step_testenv, test_siphash }; -static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx) +static void setup_siphash(struct tvec_state *tv, + const struct tvec_env *env, void *pctx, void *ctx) { - static const size_t steps[] = { 1, 5, 6, 7, 8, 23 }; - struct step step; - size_t i; + struct siphash_key *k = ctx; + ASSIGN64(k->k0, 0); ASSIGN64(k->k1, 0); +} - fn(tv->in, tv->out, 0); - tvec_check(tv, "whole buffer"); +static void bench_siphash(const struct tvec_reg *in, struct tvec_reg *out, + void *ctx) + { siphash(ctx, in[RM].v.bytes.p, in[RM].v.bytes.sz); } - for (i = 0; i < N(steps); i++) { - step.s = steps[i]; - fn(tv->in, tv->out, &step); - tvec_check(tv, "step = %lu", (unsigned long)steps[i]); - } -} +static const struct tvec_env siphash_benchenv = + { sizeof(struct siphash_key), setup_siphash, 0, before_hash }; +static const struct tvec_benchenv siphash_bench = + { TVEC_BENCHINIT, 1, -1, RM, &siphash_benchenv }; +static const struct tvec_test siphash_benchtest = + { "siphash-bench", bench_regs, &siphash_bench._env, bench_siphash }; -static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 }; +/*----- Unihash -----------------------------------------------------------*/ static const struct tvec_regdef unihash_regs[] = { { "k", &tvty_uint, RK, 0, { &tvrange_u32 } }, @@ -117,28 +175,49 @@ static const struct tvec_regdef unihash_regs[] = { TVEC_ENDREGS }; -static const struct tvec_regdef crc32_regs[] = { - { "m", &tvty_bytes, RM, 0 }, - { "h", &tvty_uint, RH, 0, { &tvrange_u32 } }, - TVEC_ENDREGS -}; +static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out, + void *ctx) +{ + const struct step *step = ctx; + unihash_info ui; + const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz; + uint32 h; -static const struct tvec_regdef bench_regs[] = { - { "msz", &tvty_buffer, RM, TVRF_ID }, - TVEC_ENDREGS -}; + unihash_setkey(&ui, in[RK].v.u); + if (!step) + out[RH].v.u = unihash(&ui, p, sz); + else { + for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s) + h = unihash_hash(&ui, h, p, step->s); + out[RH].v.u = unihash_hash(&ui, h, p, sz); + } +} -static const struct tvec_benchenv crc32_bench = - { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv }; +static const struct tvec_test unihash_test = + { "unihash", unihash_regs, &step_testenv, test_unihash }; + +static void setup_unihash(struct tvec_state *tv, + const struct tvec_env *env, void *pctx, void *ctx) + { unihash_setkey(ctx, 0); } + +static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out, + void *ctx) + { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); } + +static const struct tvec_env unihash_benchenv = + { sizeof(unihash_info), setup_unihash, 0, before_hash }; static const struct tvec_benchenv unihash_bench = { TVEC_BENCHINIT, 1, -1, RM, &unihash_benchenv }; +static const struct tvec_test unihash_benchtest = + { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash }; + +/*----- Main program ------------------------------------------------------*/ -static const struct tvec_test tests[] = { - { "crc32", crc32_regs, &step_testenv, test_crc32 }, - { "unihash", unihash_regs, &step_testenv, test_unihash }, - { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 }, - { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash }, - TVEC_ENDTESTS +static const struct tvec_test *const tests[] = { + &crc32_test, &crc32_benchtest, + &siphash_test, &siphash_benchtest, + &unihash_test, &unihash_benchtest, + 0 }; static const struct tvec_config testconfig =