diff options
author | lloyd <lloyd@randombit.net> | 2008-11-11 20:37:36 +0000 |
---|---|---|
committer | lloyd <lloyd@randombit.net> | 2008-11-11 20:37:36 +0000 |
commit | 7ffcb0d29c9b99e46498d0a8a2e4cf5e100a9d21 (patch) | |
tree | a7e09668a89ed35047691e5922eec96a1e1286a5 /src | |
parent | 966464c71c43e7c389540a795bb45ea3c3e73262 (diff) |
Add a runtime benchmarking system (for ciphers/hash/MACs)
Diffstat (limited to 'src')
-rw-r--r-- | src/benchmark/benchmark.cpp | 185 | ||||
-rw-r--r-- | src/benchmark/benchmark.h | 36 | ||||
-rw-r--r-- | src/benchmark/info.txt | 11 |
3 files changed, 232 insertions, 0 deletions
diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp new file mode 100644 index 000000000..41e41bfcc --- /dev/null +++ b/src/benchmark/benchmark.cpp @@ -0,0 +1,185 @@ +/** +* Runtime benchmarking +* (C) 2008 Jack Lloyd +*/ + +#include <botan/benchmark.h> +#include <botan/buf_comp.h> +#include <botan/block_cipher.h> +#include <botan/stream_cipher.h> +#include <botan/hash.h> +#include <botan/mac.h> +#include <botan/util.h> +#include <memory> + +namespace Botan { + +namespace { + +/** +* Benchmark BufferedComputation (hash or MAC) +*/ +std::pair<u32bit, u64bit> bench_buf_es(BufferedComputation* buf_comp, + Timer& timer, + u32bit nanoseconds_max, + const byte buf[], u32bit buf_len) + { + const u64bit start = timer.clock(); + u64bit nanoseconds_used = 0; + u32bit reps = 0; + + while(nanoseconds_used < nanoseconds_max) + { + buf_comp->update(buf, buf_len); + ++reps; + nanoseconds_used = timer.clock() - start; + } + + return std::make_pair(reps * buf_len, nanoseconds_used); + } + +/** +* Benchmark block cipher +*/ +std::pair<u32bit, u64bit> +bench_block_cipher(BlockCipher* block_cipher, + Timer& timer, + u32bit nanoseconds_max, + byte buf[], u32bit buf_len) + { + const u64bit start = timer.clock(); + u64bit nanoseconds_used = 0; + u32bit reps = 0; + + buf_len = round_down(buf_len - 1, block_cipher->BLOCK_SIZE); + + while(nanoseconds_used < nanoseconds_max) + { + for(u32bit j = 0; j <= buf_len; j += block_cipher->BLOCK_SIZE) + block_cipher->encrypt(&buf[j]); + + ++reps; + nanoseconds_used = timer.clock() - start; + } + + return std::make_pair(reps * buf_len, nanoseconds_used); + } + +/** +* Benchmark stream +*/ +std::pair<u32bit, u64bit> +bench_stream_cipher(StreamCipher* stream_cipher, + Timer& timer, + u32bit nanoseconds_max, + byte buf[], u32bit buf_len) + { + const u64bit start = timer.clock(); + u64bit nanoseconds_used = 0; + u32bit reps = 0; + + while(nanoseconds_used < nanoseconds_max) + { + stream_cipher->encrypt(buf, buf_len); + ++reps; + nanoseconds_used = timer.clock() - start; + } + + return std::make_pair(reps * buf_len, nanoseconds_used); + } + +/** +* Benchmark hash +*/ +std::pair<u32bit, u64bit> +bench_hash(HashFunction* hash, Timer& timer, + u32bit nanoseconds_max, + const byte buf[], u32bit buf_len) + { + return bench_buf_es(hash, timer, nanoseconds_max, buf, buf_len); + } + +/** +* Benchmark MAC +*/ +std::pair<u32bit, u64bit> +bench_mac(MessageAuthenticationCode* mac, + Timer& timer, + u32bit nanoseconds_max, + const byte buf[], u32bit buf_len) + { + mac->set_key(buf, mac->MAXIMUM_KEYLENGTH); + return bench_buf_es(mac, timer, nanoseconds_max, buf, buf_len); + } + +} + +std::map<std::string, double> +algorithm_benchmark(const std::string& name, + u32bit milliseconds, + Timer& timer, + RandomNumberGenerator& rng, + Algorithm_Factory& af) + { + std::vector<std::string> providers = af.providers_of(name); + std::map<std::string, double> all_results; + + if(providers.empty()) // no providers, nothing to do + return all_results; + + const u32bit ns_per_provider = + (milliseconds * 1000 * 1000) / providers.size(); + + std::vector<byte> buf(16 * 1024); + rng.randomize(&buf[0], buf.size()); + + for(u32bit i = 0; i != providers.size(); ++i) + { + const std::string provider = providers[i]; + + SCAN_Name request(name, provider); + + std::pair<u32bit, u64bit> results = std::make_pair(0, 0); + + if(const BlockCipher* proto = af.prototype_block_cipher(request)) + { + std::auto_ptr<BlockCipher> block_cipher(proto->clone()); + results = bench_block_cipher(block_cipher.get(), timer, + ns_per_provider, + &buf[0], buf.size()); + } + else if(const StreamCipher* proto = af.prototype_stream_cipher(request)) + { + std::auto_ptr<StreamCipher> stream_cipher(proto->clone()); + results = bench_stream_cipher(stream_cipher.get(), timer, + ns_per_provider, + &buf[0], buf.size()); + } + else if(const HashFunction* proto = af.prototype_hash_function(request)) + { + std::auto_ptr<HashFunction> hash(proto->clone()); + results = bench_hash(hash.get(), timer, ns_per_provider, + &buf[0], buf.size()); + } + else if(const MessageAuthenticationCode* proto = + af.prototype_mac(request)) + { + std::auto_ptr<MessageAuthenticationCode> mac(proto->clone()); + results = bench_mac(mac.get(), timer, ns_per_provider, + &buf[0], buf.size()); + } + + if(results.first && results.second) + { + /* 953.67 == 1000 * 1000 * 1000 / 1024 / 1024 - the conversion + factor from bytes per nanosecond to mebibytes per second. + */ + double speed = (953.67 * results.first) / results.second; + all_results[provider] = speed; + } + } + + return all_results; + } + +} diff --git a/src/benchmark/benchmark.h b/src/benchmark/benchmark.h new file mode 100644 index 000000000..176b038d9 --- /dev/null +++ b/src/benchmark/benchmark.h @@ -0,0 +1,36 @@ +/** +* Runtime benchmarking +* (C) 2008 Jack Lloyd +*/ + +#ifndef BOTAN_RUNTIME_BENCHMARK_H__ +#define BOTAN_RUNTIME_BENCHMARK_H__ + +#include <botan/algo_factory.h> +#include <botan/timers.h> +#include <botan/rng.h> +#include <map> +#include <string> + +namespace Botan { + +/** +Algorithm benchmark +@param name the name of the algorithm to test (cipher, hash, or MAC) +@param milliseconds total time for the benchmark to run +@param timer the timer to use +@param rng the rng to use to generate random inputs +@param af the algorithm factory used to create objects +@returns results a map from provider to speed in mebibytes per second +*/ +std::map<std::string, double> +algorithm_benchmark(const std::string& name, + u32bit milliseconds, + Timer& timer, + RandomNumberGenerator& rng, + Algorithm_Factory& af); + +} + + +#endif diff --git a/src/benchmark/info.txt b/src/benchmark/info.txt new file mode 100644 index 000000000..e9718dbb3 --- /dev/null +++ b/src/benchmark/info.txt @@ -0,0 +1,11 @@ +realname "Benchmarking" + +define RUNTIME_BENCHMARKING + +load_on auto + +<add> +benchmark.cpp +benchmark.h +</add> + |