#include #include #include #include #include #include using Botan::byte; using Botan::u64bit; #include "common.h" #include "timer.h" #include "bench.h" /* Discard output to reduce overhead */ struct BitBucket : public Botan::Filter { void write(const byte[], u32bit) {} }; Botan::Filter* lookup(const std::string&, const std::vector&, const std::string& = "All"); namespace { double bench_filter(std::string name, Botan::Filter* filter, Botan::RandomNumberGenerator& rng, double seconds) { Botan::Pipe pipe(filter, new BitBucket); std::vector buf(128 * 1024); rng.randomize(&buf[0], buf.size()); pipe.start_msg(); Timer timer(name, buf.size()); while(timer.seconds() < seconds) { timer.start(); pipe.write(&buf[0], buf.size()); timer.stop(); } pipe.end_msg(); double bytes_per_sec = timer.events() / timer.seconds(); double mbytes_per_sec = bytes_per_sec / (1024.0 * 1024.0); std::cout.setf(std::ios::fixed, std::ios::floatfield); std::cout.precision(2); std::cout << name << " " << std::string(25 - name.length(), ' '); std::cout.width(6); std::cout << mbytes_per_sec << " MiB/sec" << std::endl; return (mbytes_per_sec); } double bench(const std::string& name, const std::string& filtername, double seconds, u32bit keylen, u32bit ivlen, Botan::RandomNumberGenerator& rng) { std::vector params; Botan::SecureVector key(keylen); rng.randomize(key, key.size()); params.push_back(hex_encode(key, key.size())); //params.push_back(std::string(int(2*keylen), 'A')); params.push_back(std::string(int(2* ivlen), 'A')); Botan::Filter* filter = lookup(filtername, params); if(filter) return bench_filter(name, filter, rng, seconds); return 0; } } void benchmark(const std::string& what, Botan::RandomNumberGenerator& rng, double seconds) { try { double sum = 0; u32bit how_many = 0; std::vector algos = get_algos(); for(u32bit j = 0; j != algos.size(); j++) if(what == "All" || what == algos[j].type) { double speed = bench(algos[j].name, algos[j].filtername, seconds, algos[j].keylen, algos[j].ivlen, rng); if(speed > .00001) /* log(0) == -inf -> messed up average */ sum += std::log(speed); how_many++; } double average = std::exp(sum / static_cast(how_many)); if(what == "All") std::cout << "\nOverall speed average: " << average << std::endl; } catch(Botan::Exception& e) { std::cout << "Botan exception caught: " << e.what() << std::endl; return; } catch(std::exception& e) { std::cout << "Standard library exception caught: " << e.what() << std::endl; return; } catch(...) { std::cout << "Unknown exception caught." << std::endl; return; } } u32bit bench_algo(const std::string& name, Botan::RandomNumberGenerator& rng, double seconds) { try { std::vector algos = get_algos(); for(u32bit j = 0; j != algos.size(); j++) { if(algos[j].name == name) { bench(algos[j].name, algos[j].filtername, seconds, algos[j].keylen, algos[j].ivlen, rng); return 1; } } return 0; } catch(Botan::Exception& e) { std::cout << "Botan exception caught: " << e.what() << std::endl; return 0; } catch(std::exception& e) { std::cout << "Standard library exception caught: " << e.what() << std::endl; return 0; } catch(...) { std::cout << "Unknown exception caught." << std::endl; return 0; } }