1 /* Bitcoin does a lot of SHA of SHA. Benchmark that. */
2 #include <ccan/crypto/sha256/sha256.c>
3 #include <ccan/time/time.h>
6 void sha256_avx(void *input_data, uint32_t digest[8], uint64_t num_blks);
7 void sha256_rorx(void *input_data, uint32_t digest[8], uint64_t num_blks);
8 void sha256_rorx_x8ms(void *input_data, uint32_t digest[8], uint64_t num_blks);
9 void sha256_sse4(void *input_data, uint32_t digest[8], uint64_t num_blks);
11 int main(int argc, char *argv[])
22 n = atoi(argv[1] ? argv[1] : "1000000");
23 memset(&block, 0, sizeof(block));
24 sha256(&block.h, &n, sizeof(n));
27 for (i = 0; i < n; i++) {
28 sha256(&block.h, &block.h, sizeof(block.h));
30 diff = time_divide(time_between(time_now(), start), n);
31 printf("Normal gave %02x%02x%02x%02x%02x%02x... in %llu nsec\n",
32 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
33 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
34 (unsigned long long)time_to_nsec(diff));
36 /* Now, don't re-initialize every time; use Transform */
37 memset(&block, 0, sizeof(block));
38 sha256(&block.h, &n, sizeof(n));
39 block.u8[sizeof(block.h)] = 0x80;
40 /* Size is 256 bits */
41 block.u8[sizeof(block)-2] = 1;
44 for (i = 0; i < n; i++) {
45 struct sha256_ctx ctx = SHA256_INIT;
47 Transform(ctx.s, block.u32);
48 for (j = 0; j < sizeof(ctx.s) / sizeof(ctx.s[0]); j++)
49 block.h.u.u32[j] = cpu_to_be32(ctx.s[j]);
51 diff = time_divide(time_between(time_now(), start), n);
52 printf("Transform gave %02x%02x%02x%02x%02x%02x... in %llu nsec\n",
53 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
54 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
55 (unsigned long long)time_to_nsec(diff));
57 /* Now, assembler variants */
58 sha256(&block.h, &n, sizeof(n));
61 for (i = 0; i < n; i++) {
62 struct sha256_ctx ctx = SHA256_INIT;
64 sha256_rorx(block.u32, ctx.s, 1);
65 for (j = 0; j < sizeof(ctx.s) / sizeof(ctx.s[0]); j++)
66 block.h.u.u32[j] = cpu_to_be32(ctx.s[j]);
68 diff = time_divide(time_between(time_now(), start), n);
69 printf("Asm rorx for %02x%02x%02x%02x%02x%02x... is %llu nsec\n",
70 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
71 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
72 (unsigned long long)time_to_nsec(diff));
74 sha256(&block.h, &n, sizeof(n));
77 for (i = 0; i < n; i++) {
78 struct sha256_ctx ctx = SHA256_INIT;
80 sha256_sse4(block.u32, ctx.s, 1);
81 for (j = 0; j < sizeof(ctx.s) / sizeof(ctx.s[0]); j++)
82 block.h.u.u32[j] = cpu_to_be32(ctx.s[j]);
84 diff = time_divide(time_between(time_now(), start), n);
85 printf("Asm SSE4 for %02x%02x%02x%02x%02x%02x... is %llu nsec\n",
86 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
87 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
88 (unsigned long long)time_to_nsec(diff));
90 sha256(&block.h, &n, sizeof(n));
92 for (i = 0; i < n; i++) {
93 struct sha256_ctx ctx = SHA256_INIT;
95 sha256_rorx_x8ms(block.u32, ctx.s, 1);
96 for (j = 0; j < sizeof(ctx.s) / sizeof(ctx.s[0]); j++)
97 block.h.u.u32[j] = cpu_to_be32(ctx.s[j]);
99 diff = time_divide(time_between(time_now(), start), n);
100 printf("Asm RORx-x8ms for %02x%02x%02x%02x%02x%02x... is %llu nsec\n",
101 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
102 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
103 (unsigned long long)time_to_nsec(diff));
105 sha256(&block.h, &n, sizeof(n));
107 for (i = 0; i < n; i++) {
108 struct sha256_ctx ctx = SHA256_INIT;
110 sha256_avx(block.u32, ctx.s, 1);
111 for (j = 0; j < sizeof(ctx.s) / sizeof(ctx.s[0]); j++)
112 block.h.u.u32[j] = cpu_to_be32(ctx.s[j]);
114 diff = time_divide(time_between(time_now(), start), n);
115 printf("Asm AVX for %02x%02x%02x%02x%02x%02x... is %llu nsec\n",
116 block.h.u.u8[0], block.h.u.u8[1], block.h.u.u8[2],
117 block.h.u.u8[3], block.h.u.u8[4], block.h.u.u8[5],
118 (unsigned long long)time_to_nsec(diff));