| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 <fmt/core.h> |
| #include <rocksdb/env.h> |
| #include <rocksdb/statistics.h> |
| #include <stdio.h> |
| #include <algorithm> |
| #include <unordered_map> |
| |
| #include "config.h" |
| #include "statistics.h" |
| #include "test/bench_test/utils.h" |
| |
| namespace pegasus { |
| namespace test { |
| std::unordered_map<operation_type, std::string, std::hash<unsigned char>> operation_type_string = { |
| {kUnknown, "unKnown"}, |
| {kRead, "read"}, |
| {kWrite, "write"}, |
| {kDelete, "delete"}, |
| {kMultiSet, "multiSet"}, |
| {kMultiGet, "multiGet"}}; |
| |
| statistics::statistics(std::shared_ptr<rocksdb::Statistics> hist_stats) |
| { |
| _next_report = 100; |
| _done = 0; |
| _bytes = 0; |
| _start = config::instance().env->NowMicros(); |
| _last_op_finish = _start; |
| _finish = _start; |
| _hist_stats = hist_stats; |
| _message.clear(); |
| } |
| |
| void statistics::start() |
| { |
| _start = config::instance().env->NowMicros(); |
| _last_op_finish = _start; |
| _finish = _start; |
| } |
| |
| void statistics::merge(const statistics &other) |
| { |
| _done += other._done; |
| _bytes += other._bytes; |
| _start = std::min(other._start, _start); |
| _finish = std::max(other._finish, _finish); |
| this->add_message(other._message); |
| } |
| |
| void statistics::stop() { _finish = config::instance().env->NowMicros(); } |
| |
| void statistics::finished_ops(int64_t num_ops, enum operation_type op_type) |
| { |
| uint64_t now = config::instance().env->NowMicros(); |
| uint64_t micros = now - _last_op_finish; |
| _last_op_finish = now; |
| |
| // if there is a long operation, print warning message |
| if (micros > 20000) { |
| fmt::print(stderr, "long op: {} micros\r", micros); |
| } |
| |
| // print the benchmark running status |
| _done += num_ops; |
| if (_done >= _next_report) { |
| _next_report += report_step(_next_report); |
| fmt::print(stderr, "... finished {} ops\r", _done); |
| } |
| |
| // add excution time of this operation to _hist_stats |
| if (_hist_stats) { |
| _hist_stats->measureTime(op_type, micros); |
| } |
| } |
| |
| void statistics::report(operation_type op_type) |
| { |
| // Pretend at least one op was done in case we are running a benchmark |
| // that does not call finished_ops(). |
| if (_done < 1) |
| _done = 1; |
| |
| // elasped time(s) |
| double elapsed = (_finish - _start) * 1e-6; |
| |
| // append rate(MBytes) and _message to extra |
| std::string extra; |
| if (_bytes > 0) { |
| // Rate is computed on actual elapsed time, not the sum of per-thread |
| // elapsed times. |
| extra = fmt::format("{} MB/s ", (_bytes >> 20) / elapsed); |
| } |
| extra.append(_message); |
| |
| // print report |
| fmt::print(stdout, |
| "Statistics for {}: \n{} micros/op; {} ops/sec; {}\n", |
| operation_type_string[op_type], |
| elapsed * 1e6 / _done, |
| static_cast<long>(_done / elapsed), |
| extra); |
| |
| // print histogram if _hist_stats is not NULL |
| if (_hist_stats) { |
| fmt::print(stdout, "{}\n", _hist_stats->getHistogramString(op_type)); |
| } |
| } |
| |
| void statistics::add_message(const std::string &msg) |
| { |
| if (msg.empty()) |
| return; |
| |
| if (!_message.empty()) { |
| _message.push_back(' '); |
| } |
| _message.append(msg); |
| } |
| |
| void statistics::add_bytes(int64_t n) { _bytes += n; } |
| |
| uint32_t statistics::report_step(uint64_t current_report) const |
| { |
| uint32_t step = 0; |
| switch (current_report) { |
| case 0 ... 999: |
| step = 100; |
| break; |
| case 1000 ... 4999: |
| step = 500; |
| break; |
| case 5000 ... 9999: |
| step = 1000; |
| break; |
| case 10000 ... 49999: |
| step = 5000; |
| break; |
| case 50000 ... 99999: |
| step = 10000; |
| break; |
| case 100000 ... 499999: |
| step = 50000; |
| break; |
| default: |
| step = 100000; |
| break; |
| } |
| |
| return step; |
| } |
| } // namespace test |
| } // namespace pegasus |