cachelib/cachebench/runner/Stressor.cpp (137 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * 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 "cachelib/cachebench/runner/Stressor.h" #include "cachelib/allocator/CacheAllocator.h" #include "cachelib/cachebench/runner/CacheStressor.h" #include "cachelib/cachebench/runner/FastShutdown.h" #include "cachelib/cachebench/runner/IntegrationStressor.h" #include "cachelib/cachebench/workload/OnlineGenerator.h" #include "cachelib/cachebench/workload/PieceWiseReplayGenerator.h" #include "cachelib/cachebench/workload/ReplayGenerator.h" #include "cachelib/cachebench/workload/WorkloadGenerator.h" #include "cachelib/common/Utils.h" namespace facebook { namespace cachelib { namespace cachebench { ThroughputStats& ThroughputStats::operator+=(const ThroughputStats& other) { set += other.set; setFailure += other.setFailure; get += other.get; getMiss += other.getMiss; del += other.del; update += other.update; updateMiss += other.updateMiss; delNotFound += other.delNotFound; addChained += other.addChained; addChainedFailure += other.addChainedFailure; ops += other.ops; return *this; } void ThroughputStats::render(uint64_t elapsedTimeNs, std::ostream& out) const { const double elapsedSecs = elapsedTimeNs / static_cast<double>(1e9); const uint64_t setPerSec = util::narrow_cast<uint64_t>(set / elapsedSecs); const double setSuccessRate = set == 0 ? 0.0 : 100.0 * (set - setFailure) / set; const uint64_t getPerSec = util::narrow_cast<uint64_t>(get / elapsedSecs); const double getSuccessRate = get == 0 ? 0.0 : 100.0 * (get - getMiss) / get; const uint64_t delPerSec = util::narrow_cast<uint64_t>(del / elapsedSecs); const double delSuccessRate = del == 0 ? 0.0 : 100.0 * (del - delNotFound) / del; const uint64_t updatePerSec = util::narrow_cast<uint64_t>(update / elapsedSecs); const double updateSuccessRate = update == 0 ? 0.0 : 100.0 * (update - updateMiss) / update; const uint64_t addChainedPerSec = util::narrow_cast<uint64_t>(addChained / elapsedSecs); const double addChainedSuccessRate = addChained == 0 ? 0.0 : 100.0 * (addChained - addChainedFailure) / addChained; out << std::fixed; out << folly::sformat("{:10}: {:.2f} million", "Total Ops", ops / 1e6) << std::endl; out << folly::sformat("{:10}: {:,}", "Total sets", set) << std::endl; auto outFn = [&out](folly::StringPiece k1, uint64_t v1, folly::StringPiece k2, double v2) { out << folly::sformat("{:10}: {:9,}/s, {:10}: {:6.2f}%", k1, v1, k2, v2) << std::endl; }; outFn("get", getPerSec, "success", getSuccessRate); outFn("set", setPerSec, "success", setSuccessRate); outFn("del", delPerSec, "found", delSuccessRate); if (update > 0) { outFn("update", updatePerSec, "success", updateSuccessRate); } if (addChained > 0) { outFn("addChained", addChainedPerSec, "success", addChainedSuccessRate); } } void ThroughputStats::render(uint64_t elapsedTimeNs, folly::UserCounters& counters) const { const double elapsedSecs = elapsedTimeNs / static_cast<double>(1e9); const uint64_t setPerSec = util::narrow_cast<uint64_t>(set / elapsedSecs); const double setSuccessRate = set == 0 ? 0.0 : 100.0 * (set - setFailure) / set; const uint64_t getPerSec = util::narrow_cast<uint64_t>(get / elapsedSecs); const double getSuccessRate = get == 0 ? 0.0 : 100.0 * (get - getMiss) / get; const uint64_t delPerSec = util::narrow_cast<uint64_t>(del / elapsedSecs); const double delSuccessRate = del == 0 ? 0.0 : 100.0 * (del - delNotFound) / del; const uint64_t addChainedPerSec = util::narrow_cast<uint64_t>(addChained / elapsedSecs); const double addChainedSuccessRate = addChained == 0 ? 0.0 : 100.0 * (addChained - addChainedFailure) / addChained; counters["ops"] = ops; counters["total_sets"] = set; counters["get_per_sec"] = getPerSec; counters["get_suc_rate"] = util::narrow_cast<uint64_t>(getSuccessRate); counters["set_per_sec"] = setPerSec; counters["set_suc_rate"] = util::narrow_cast<uint64_t>(setSuccessRate); counters["del_per_sec"] = delPerSec; counters["del_suc_rate"] = util::narrow_cast<uint64_t>(delSuccessRate); counters["addChain_per_sec"] = addChainedPerSec; counters["addChain_suc_rate"] = util::narrow_cast<uint64_t>(addChainedSuccessRate); } namespace { std::unique_ptr<GeneratorBase> makeGenerator(const StressorConfig& config) { if (config.generator == "piecewise-replay") { return std::make_unique<PieceWiseReplayGenerator>(config); } else if (config.generator == "replay") { return std::make_unique<ReplayGenerator>(config); } else if (config.generator.empty() || config.generator == "workload") { // TODO: Remove the empty() check once we label workload-based configs // properly return std::make_unique<WorkloadGenerator>(config); } else if (config.generator == "online") { return std::make_unique<OnlineGenerator>(config); } else { throw std::invalid_argument("Invalid config"); } } } // namespace std::unique_ptr<Stressor> Stressor::makeStressor( const CacheConfig& cacheConfig, const StressorConfig& stressorConfig) { if (stressorConfig.name == "high_refcount") { return std::make_unique<HighRefcountStressor>(cacheConfig, stressorConfig.numOps); } else if (stressorConfig.name == "cachelib_map") { return std::make_unique<CachelibMapStressor>(cacheConfig, stressorConfig.numOps); } else if (stressorConfig.name == "cachelib_range_map") { return std::make_unique<CachelibRangeMapStressor>(cacheConfig, stressorConfig.numOps); } else if (stressorConfig.name == "fast_shutdown") { return std::make_unique<FastShutdownStressor>(cacheConfig, stressorConfig.numOps); } else { auto generator = makeGenerator(stressorConfig); if (cacheConfig.allocator == "LRU") { // default allocator is LRU, other allocator types should be added here return std::make_unique<CacheStressor<LruAllocator>>( cacheConfig, stressorConfig, std::move(generator)); } else if (cacheConfig.allocator == "LRU2Q") { return std::make_unique<CacheStressor<Lru2QAllocator>>( cacheConfig, stressorConfig, std::move(generator)); } } throw std::invalid_argument("Invalid config"); } } // namespace cachebench } // namespace cachelib } // namespace facebook