/// /// \author John Farrier /// /// \copyright Copyright 2015, 2016, 2017, 2018. 2019 John Farrier /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// #include #include #include #include #include #include #include #include using namespace celero; class Experiment::Impl { public: Impl() : results(), benchmark(), factory(), name(), baselineUnit(0), baselineTarget(0), samples(0), iterations(0), threads(1), totalRunTime(0), isBaselineCase(false) { } Impl(std::weak_ptr bm, const std::string& n, const uint64_t s, const uint64_t c, const uint64_t t, const double pBaselineTarget) : results(), benchmark(bm), factory(), name(n), baselineUnit(0), baselineTarget(pBaselineTarget), samples(s), iterations(c), threads(t), totalRunTime(0), isBaselineCase(false) { } explicit Impl(std::weak_ptr bm) : results(), benchmark(bm), factory(), name(), baselineUnit(0), baselineTarget(0), samples(0), iterations(0), threads(1), totalRunTime(0), isBaselineCase(false) { } /// There is one result for each problem space value. /// In the event there are not any problem spaces, there shal be a single result. std::vector> results; /// The owning benchmark object which groups together all experiments. std::weak_ptr benchmark; /// The factory to associate with this benchmark. std::shared_ptr factory; /// The name of this experiment. std::string name; /// The number of microseconds per test (which makes up one baseline unit). double baselineUnit{0}; /// Used to pass/fail benchmarks when outputting JUnit. double baselineTarget{0}; /// Test samples to complete. uint64_t samples{0}; /// Iterations per test run. (Size of each sample.) uint64_t iterations{0}; /// Threads per test run. uint64_t threads{0}; /// The best run time for this test uint64_t totalRunTime{0}; bool isBaselineCase{false}; }; Experiment::Experiment() : pimpl() { } Experiment::Experiment(std::weak_ptr benchmark) : pimpl(benchmark) { } Experiment::Experiment(std::weak_ptr benchmark, const std::string& name, uint64_t samples, uint64_t iterations, uint64_t threads, double baselineTarget) : pimpl(benchmark, name, samples, iterations, threads, baselineTarget) { } Experiment::Experiment(const Experiment&) { } Experiment::~Experiment() { } std::shared_ptr Experiment::getBenchmark() { return this->pimpl->benchmark.lock(); } void Experiment::setName(const std::string& x) { this->pimpl->name = x; } std::string Experiment::getName() const { return this->pimpl->name; } void Experiment::setSamples(uint64_t x) { this->pimpl->samples = x; } uint64_t Experiment::getSamples() const { return this->pimpl->samples; } void Experiment::setIterations(uint64_t x) { this->pimpl->iterations = x; } uint64_t Experiment::getIterations() const { return this->pimpl->iterations; } void Experiment::setThreads(uint64_t x) { this->pimpl->threads = x; } uint64_t Experiment::getThreads() const { return this->pimpl->threads; } Experiment::operator std::string() const { auto output = this->getShort(); if(this->getSamples() > 0) { output += " -- " + std::to_string(this->getSamples()); if(this->getSamples() == 1) { output += " run, "; } else { output += " samples, "; } } else { output += " -- Auto Run, "; } output += std::to_string(this->getIterations()); if(this->getIterations() == 1) { output += " iteration per run,"; } else { output += " iterations per run,"; } if(this->getThreads() == 1) { output += " thread per run."; } else { output += " threads per run."; } return output; } std::string Experiment::getShort() const { auto bm = this->pimpl->benchmark.lock(); if(bm != nullptr) { return bm->getName() + "." + this->getName(); } return this->getName(); } void Experiment::setBaselineTarget(double x) { this->pimpl->baselineTarget = x; } double Experiment::getBaselineTarget() const { return this->pimpl->baselineTarget; } void Experiment::incrementTotalRunTime(const uint64_t x) { this->pimpl->totalRunTime += x; } uint64_t Experiment::getTotalRunTime() const { return this->pimpl->totalRunTime; } void Experiment::setIsBaselineCase(bool x) { this->pimpl->isBaselineCase = x; } bool Experiment::getIsBaselineCase() const { return this->pimpl->isBaselineCase; } void Experiment::setFactory(std::shared_ptr x) { this->pimpl->factory = x; } std::shared_ptr Experiment::getFactory() const { return this->pimpl->factory; } void Experiment::addProblemSpace(int64_t x, double scale, uint64_t iterations) { auto r = std::make_shared(this); r->setProblemSpaceValue(x, scale, iterations); this->pimpl->results.push_back(r); } size_t Experiment::getResultSize() { if(this->pimpl->results.empty() == true) { auto defaultResult = std::make_shared(this); defaultResult->setProblemSpaceValue(static_cast(TestFixture::Constants::NoProblemSpaceValue), 1.0, this->getIterations()); this->pimpl->results.push_back(defaultResult); } return this->pimpl->results.size(); } std::shared_ptr Experiment::getResult(size_t x) { // get the result OR thrown an exception if the result list is empty; return this->pimpl->results.at(x); } std::shared_ptr Experiment::getResultByValue(int64_t x) { std::shared_ptr r; const auto found = std::find_if(std::begin(this->pimpl->results), std::end(this->pimpl->results), [x](std::shared_ptr i) -> bool { return (i->getProblemSpaceValue() == x); }); if(found != std::end(this->pimpl->results)) { r = (*found); } return r; }