[CRYPTO] tcrypt: Speed benchmark support for digest algorithms
Michal Ludvig [Tue, 30 May 2006 12:04:19 +0000 (22:04 +1000)]
This patch adds speed tests (benchmarks) for digest algorithms.
Tests are run with different buffer sizes (16 bytes, ... 8 kBytes)
and with each buffer multiple tests are run with different update()
sizes (e.g. hash 64 bytes buffer in four 16 byte updates).
There is no correctness checking of the result and all tests and
algorithms use the same input buffer.

Signed-off-by: Michal Ludvig <michal@logix.cz>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

crypto/tcrypt.c
crypto/tcrypt.h

index 7bf93c5..e52f56c 100644 (file)
@@ -570,6 +570,122 @@ out:
        crypto_free_tfm(tfm);
 }
 
+static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen,
+                               int plen, char *out, int sec)
+{
+       struct scatterlist sg[1];
+       unsigned long start, end;
+       int bcount, pcount;
+
+       for (start = jiffies, end = start + sec * HZ, bcount = 0;
+            time_before(jiffies, end); bcount++) {
+               crypto_digest_init(tfm);
+               for (pcount = 0; pcount < blen; pcount += plen) {
+                       sg_set_buf(sg, p + pcount, plen);
+                       crypto_digest_update(tfm, sg, 1);
+               }
+               /* we assume there is enough space in 'out' for the result */
+               crypto_digest_final(tfm, out);
+       }
+
+       printk("%6u opers/sec, %9lu bytes/sec\n",
+              bcount / sec, ((long)bcount * blen) / sec);
+
+       return;
+}
+
+static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
+                              int plen, char *out)
+{
+       struct scatterlist sg[1];
+       unsigned long cycles = 0;
+       int i, pcount;
+
+       local_bh_disable();
+       local_irq_disable();
+
+       /* Warm-up run. */
+       for (i = 0; i < 4; i++) {
+               crypto_digest_init(tfm);
+               for (pcount = 0; pcount < blen; pcount += plen) {
+                       sg_set_buf(sg, p + pcount, plen);
+                       crypto_digest_update(tfm, sg, 1);
+               }
+               crypto_digest_final(tfm, out);
+       }
+
+       /* The real thing. */
+       for (i = 0; i < 8; i++) {
+               cycles_t start, end;
+
+               crypto_digest_init(tfm);
+
+               start = get_cycles();
+
+               for (pcount = 0; pcount < blen; pcount += plen) {
+                       sg_set_buf(sg, p + pcount, plen);
+                       crypto_digest_update(tfm, sg, 1);
+               }
+               crypto_digest_final(tfm, out);
+
+               end = get_cycles();
+
+               cycles += end - start;
+       }
+
+       local_irq_enable();
+       local_bh_enable();
+
+       printk("%6lu cycles/operation, %4lu cycles/byte\n",
+              cycles / 8, cycles / (8 * blen));
+
+       return;
+}
+
+static void test_digest_speed(char *algo, unsigned int sec,
+                             struct digest_speed *speed)
+{
+       struct crypto_tfm *tfm;
+       char output[1024];
+       int i;
+
+       printk("\ntesting speed of %s\n", algo);
+
+       tfm = crypto_alloc_tfm(algo, 0);
+
+       if (tfm == NULL) {
+               printk("failed to load transform for %s\n", algo);
+               return;
+       }
+
+       if (crypto_tfm_alg_digestsize(tfm) > sizeof(output)) {
+               printk("digestsize(%u) > outputbuffer(%zu)\n",
+                      crypto_tfm_alg_digestsize(tfm), sizeof(output));
+               goto out;
+       }
+
+       for (i = 0; speed[i].blen != 0; i++) {
+               if (speed[i].blen > TVMEMSIZE) {
+                       printk("template (%u) too big for tvmem (%u)\n",
+                              speed[i].blen, TVMEMSIZE);
+                       goto out;
+               }
+
+               printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
+                      i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
+
+               memset(tvmem, 0xff, speed[i].blen);
+
+               if (sec)
+                       test_digest_jiffies(tfm, tvmem, speed[i].blen, speed[i].plen, output, sec);
+               else
+                       test_digest_cycles(tfm, tvmem, speed[i].blen, speed[i].plen, output);
+       }
+
+out:
+       crypto_free_tfm(tfm);
+}
+
 static void test_deflate(void)
 {
        unsigned int i;
@@ -1086,6 +1202,60 @@ static void do_test(void)
                                  des_speed_template);
                break;
 
+       case 300:
+               /* fall through */
+
+       case 301:
+               test_digest_speed("md4", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 302:
+               test_digest_speed("md5", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 303:
+               test_digest_speed("sha1", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 304:
+               test_digest_speed("sha256", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 305:
+               test_digest_speed("sha384", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 306:
+               test_digest_speed("sha512", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 307:
+               test_digest_speed("wp256", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 308:
+               test_digest_speed("wp384", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 309:
+               test_digest_speed("wp512", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 310:
+               test_digest_speed("tgr128", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 311:
+               test_digest_speed("tgr160", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 312:
+               test_digest_speed("tgr192", sec, generic_digest_speed_template);
+               if (mode > 300 && mode < 400) break;
+
+       case 399:
+               break;
+
        case 1000:
                test_available();
                break;
index 1f683ba..1fac560 100644 (file)
@@ -65,6 +65,11 @@ struct cipher_speed {
        unsigned int blen;
 };
 
+struct digest_speed {
+       unsigned int blen;      /* buffer length */
+       unsigned int plen;      /* per-update length */
+};
+
 /*
  * MD4 test vectors from RFC1320
  */
@@ -2975,4 +2980,35 @@ static struct cipher_speed des_speed_template[] = {
        {  .klen = 0, .blen = 0, }
 };
 
+/*
+ * Digest speed tests
+ */
+static struct digest_speed generic_digest_speed_template[] = {
+       { .blen = 16,   .plen = 16, },
+       { .blen = 64,   .plen = 16, },
+       { .blen = 64,   .plen = 64, },
+       { .blen = 256,  .plen = 16, },
+       { .blen = 256,  .plen = 64, },
+       { .blen = 256,  .plen = 256, },
+       { .blen = 1024, .plen = 16, },
+       { .blen = 1024, .plen = 256, },
+       { .blen = 1024, .plen = 1024, },
+       { .blen = 2048, .plen = 16, },
+       { .blen = 2048, .plen = 256, },
+       { .blen = 2048, .plen = 1024, },
+       { .blen = 2048, .plen = 2048, },
+       { .blen = 4096, .plen = 16, },
+       { .blen = 4096, .plen = 256, },
+       { .blen = 4096, .plen = 1024, },
+       { .blen = 4096, .plen = 4096, },
+       { .blen = 8192, .plen = 16, },
+       { .blen = 8192, .plen = 256, },
+       { .blen = 8192, .plen = 1024, },
+       { .blen = 8192, .plen = 4096, },
+       { .blen = 8192, .plen = 8192, },
+
+       /* End marker */
+       {  .blen = 0,   .plen = 0, }
+};
+
 #endif /* _CRYPTO_TCRYPT_H */