Botan 1.10.17
benchmark.cpp
Go to the documentation of this file.
1/*
2* Runtime benchmarking
3* (C) 2008 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/benchmark.h>
9#include <botan/buf_comp.h>
10#include <botan/block_cipher.h>
11#include <botan/stream_cipher.h>
12#include <botan/hash.h>
13#include <botan/mac.h>
14#include <botan/time.h>
15#include <memory>
16
17namespace Botan {
18
19namespace {
20
21/**
22* Benchmark Buffered_Computation (hash or MAC)
23*/
24std::pair<u64bit, u64bit> bench_buf_comp(Buffered_Computation* buf_comp,
25 u64bit nanoseconds_max,
26 const byte buf[], size_t buf_len)
27 {
28 u64bit reps = 0;
29 u64bit nanoseconds_used = 0;
30
31 while(nanoseconds_used < nanoseconds_max)
32 {
33 const u64bit start = get_nanoseconds_clock();
34 buf_comp->update(buf, buf_len);
35 nanoseconds_used += get_nanoseconds_clock() - start;
36
37 ++reps;
38 }
39
40 return std::make_pair(reps * buf_len, nanoseconds_used);
41 }
42
43/**
44* Benchmark block cipher
45*/
46std::pair<u64bit, u64bit>
47bench_block_cipher(BlockCipher* block_cipher,
48 u64bit nanoseconds_max,
49 byte buf[], size_t buf_len)
50 {
51 const size_t in_blocks = buf_len / block_cipher->block_size();
52
53 u64bit reps = 0;
54 u64bit nanoseconds_used = 0;
55
56 block_cipher->set_key(buf, block_cipher->maximum_keylength());
57
58 while(nanoseconds_used < nanoseconds_max)
59 {
60 const u64bit start = get_nanoseconds_clock();
61 block_cipher->encrypt_n(buf, buf, in_blocks);
62 nanoseconds_used += get_nanoseconds_clock() - start;
63
64 ++reps;
65 }
66
67 return std::make_pair(reps * in_blocks * block_cipher->block_size(),
68 nanoseconds_used);
69 }
70
71/**
72* Benchmark stream
73*/
74std::pair<u64bit, u64bit>
75bench_stream_cipher(StreamCipher* stream_cipher,
76 u64bit nanoseconds_max,
77 byte buf[], size_t buf_len)
78 {
79 u64bit reps = 0;
80 u64bit nanoseconds_used = 0;
81
82 stream_cipher->set_key(buf, stream_cipher->maximum_keylength());
83
84 while(nanoseconds_used < nanoseconds_max)
85 {
86 const u64bit start = get_nanoseconds_clock();
87 stream_cipher->cipher1(buf, buf_len);
88 nanoseconds_used += get_nanoseconds_clock() - start;
89
90 ++reps;
91 }
92
93 return std::make_pair(reps * buf_len, nanoseconds_used);
94 }
95
96/**
97* Benchmark hash
98*/
99std::pair<u64bit, u64bit>
100bench_hash(HashFunction* hash,
101 u64bit nanoseconds_max,
102 const byte buf[], size_t buf_len)
103 {
104 return bench_buf_comp(hash, nanoseconds_max, buf, buf_len);
105 }
106
107/**
108* Benchmark MAC
109*/
110std::pair<u64bit, u64bit>
111bench_mac(MessageAuthenticationCode* mac,
112 u64bit nanoseconds_max,
113 const byte buf[], size_t buf_len)
114 {
115 mac->set_key(buf, mac->maximum_keylength());
116 return bench_buf_comp(mac, nanoseconds_max, buf, buf_len);
117 }
118
119}
120
121std::map<std::string, double>
122algorithm_benchmark(const std::string& name,
125 u32bit milliseconds,
126 size_t buf_size)
127 {
128 std::vector<std::string> providers = af.providers_of(name);
129 std::map<std::string, double> all_results;
130
131 if(providers.empty()) // no providers, nothing to do
132 return all_results;
133
134 const u64bit ns_per_provider =
135 (static_cast<u64bit>(milliseconds) * 1000 * 1000) / providers.size();
136
137 std::vector<byte> buf(buf_size * 1024);
138 rng.randomize(&buf[0], buf.size());
139
140 for(size_t i = 0; i != providers.size(); ++i)
141 {
142 const std::string provider = providers[i];
143
144 std::pair<u64bit, u64bit> results(0, 0);
145
146 if(const BlockCipher* proto =
147 af.prototype_block_cipher(name, provider))
148 {
149 std::auto_ptr<BlockCipher> block_cipher(proto->clone());
150 results = bench_block_cipher(block_cipher.get(),
151 ns_per_provider,
152 &buf[0], buf.size());
153 }
154 else if(const StreamCipher* proto =
155 af.prototype_stream_cipher(name, provider))
156 {
157 std::auto_ptr<StreamCipher> stream_cipher(proto->clone());
158 results = bench_stream_cipher(stream_cipher.get(),
159 ns_per_provider,
160 &buf[0], buf.size());
161 }
162 else if(const HashFunction* proto =
163 af.prototype_hash_function(name, provider))
164 {
165 std::auto_ptr<HashFunction> hash(proto->clone());
166 results = bench_hash(hash.get(), ns_per_provider,
167 &buf[0], buf.size());
168 }
169 else if(const MessageAuthenticationCode* proto =
170 af.prototype_mac(name, provider))
171 {
172 std::auto_ptr<MessageAuthenticationCode> mac(proto->clone());
173 results = bench_mac(mac.get(), ns_per_provider,
174 &buf[0], buf.size());
175 }
176
177 if(results.first && results.second)
178 {
179 /* 953.67 == 1000 * 1000 * 1000 / 1024 / 1024 - the conversion
180 factor from bytes per nanosecond to mebibytes per second.
181 */
182 double speed = (953.67 * results.first) / results.second;
183 all_results[provider] = speed;
184 }
185 }
186
187 return all_results;
188 }
189
190}
std::vector< std::string > providers_of(const std::string &algo_spec)
const HashFunction * prototype_hash_function(const std::string &algo_spec, const std::string &provider="")
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
const MessageAuthenticationCode * prototype_mac(const std::string &algo_spec, const std::string &provider="")
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
virtual void randomize(byte output[], size_t length)=0
u64bit get_nanoseconds_clock()
Definition time.cpp:93
unsigned long long u64bit
Definition types.h:49
std::map< std::string, double > algorithm_benchmark(const std::string &name, Algorithm_Factory &af, RandomNumberGenerator &rng, u32bit milliseconds, size_t buf_size)
unsigned int u32bit
Definition types.h:32