In this code drop we introduce the benchmarking tests that allow us to
compare the performance of different implementations. Like the other
tests, any implementation can link with them to create their own
binary.
There are two types of benchmarks:
1 - Throughput, which measures the speed that a function can process
information (bits per second). These are used for AEAD decrypt
and license white-box decrypt functions.
2 - Samples, which measures the min, 25% percentile, median, 75%
percentile, and max observed values. These is used for all other
functions as a way to measure the execute duration of a call.
The other change in this code drop is the update to the unmasking
function to only unmask a subset of the bytes in the masked buffer.
This was added to better align with the decoder behaviour in the CDM.
79 lines
2.4 KiB
C++
79 lines
2.4 KiB
C++
// Copyright 2020 Google LLC. All Rights Reserved.
|
|
|
|
#include "benchmarking/measurements.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "base/logging.h"
|
|
|
|
namespace widevine {
|
|
namespace {
|
|
size_t RoundUp(size_t num, size_t denum) {
|
|
return (num + denum - 1) / denum;
|
|
}
|
|
} // namespace
|
|
|
|
void Timer::Reset() {
|
|
start_ = Clock::now();
|
|
}
|
|
|
|
Period Timer::Get() const {
|
|
const auto now = Clock::now();
|
|
return std::chrono::duration_cast<Period>(now - start_);
|
|
}
|
|
|
|
Throughput::Throughput() : bytes(0), microseconds(0), bits_per_second(0) {}
|
|
|
|
Throughput::Throughput(const Period& duration, size_t bytes) {
|
|
this->bytes = bytes;
|
|
microseconds = duration.count();
|
|
|
|
bits_per_second = 0;
|
|
|
|
if (microseconds > 0) {
|
|
// Make sure to only do one division to ensure that we are not loosing too
|
|
// much information as we are avoiding floating-point values.
|
|
bits_per_second = (bytes * 8 * 1000 * 1000) / microseconds;
|
|
}
|
|
}
|
|
|
|
const Period& Sampler::Percentile::Get(size_t percentile) const {
|
|
// Nearest-rank method:
|
|
// https://en.wikipedia.org/wiki/Percentile#The_nearest-rank_method
|
|
const size_t index = RoundUp(samples_.size() * percentile, 100);
|
|
|
|
// The index will be from 1 to N, but we need it to be 0 to N-1.
|
|
return samples_[index - 1];
|
|
}
|
|
|
|
void Sampler::Push(const Period& period) {
|
|
samples_.push_back(period);
|
|
}
|
|
|
|
void PrettyPrint(const std::string& title,
|
|
const Throughput& throughput,
|
|
size_t bytes_per_call) {
|
|
LOG(INFO) << title;
|
|
LOG(INFO) << " bytes per call: " << bytes_per_call;
|
|
LOG(INFO) << " bytes: " << throughput.bytes;
|
|
LOG(INFO) << " microseconds: " << throughput.microseconds;
|
|
LOG(INFO) << " bits per second: " << throughput.bits_per_second;
|
|
}
|
|
|
|
void PrettyPrint(const std::string& title,
|
|
const Sampler& samples,
|
|
size_t per_sample_size) {
|
|
const auto& percentiles = samples.Percentiles();
|
|
|
|
LOG(INFO) << title;
|
|
LOG(INFO) << " Sample Size: " << samples.SampleSize() << " ("
|
|
<< per_sample_size << " bytes)";
|
|
LOG(INFO) << " Min (0%): " << percentiles.Get(0).count() << " us";
|
|
LOG(INFO) << " 25%: " << percentiles.Get(25).count() << " us";
|
|
LOG(INFO) << " Median (50%): " << percentiles.Get(50).count() << " us";
|
|
LOG(INFO) << " 75%: " << percentiles.Get(75).count() << " us";
|
|
LOG(INFO) << " Max (100%): " << percentiles.Get(100).count() << " us";
|
|
}
|
|
|
|
} // namespace widevine
|