blob: 6f997a02282b06b3100a15b19e3dee94f2c80a82 [file]
// Copyright 2022 The Centipede Authors.
//
// 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
//
// https://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 "./centipede/stats.h"
#include <algorithm>
#include <map>
#include <numeric>
#include <string>
#include "absl/container/flat_hash_set.h"
#include "absl/types/span.h"
#include "./centipede/environment.h"
#include "./centipede/logging.h"
namespace centipede {
namespace {
// Helper for PrintExperimentStats().
// Prints the experiment summary for the `field`.
void PrintExperimentStatsForOneStatValue(absl::Span<const Stats> stats_vec,
absl::Span<const Environment> env_vec,
std::ostream &os,
std::atomic<uint64_t> Stats::*field) {
CHECK_EQ(stats_vec.size(), env_vec.size());
// Maps experiment names to indices in env_vec/stats_vec.
// We use std::map because we want lexicographic order of experiment names.
std::map<std::string_view, std::vector<size_t>> experiment_to_indices;
for (size_t i = 0; i < env_vec.size(); ++i) {
experiment_to_indices[env_vec[i].experiment_name].push_back(i);
}
// Iterate over every experiment_name.
for (const auto &[experiment_name, experiment_indices] :
experiment_to_indices) {
os << experiment_name << ": ";
std::vector<uint64_t> stat_values;
CHECK_NE(experiment_indices.size(), 0);
// Get the required stat fields into a vector `stat_values`.
stat_values.reserve(experiment_indices.size());
for (const auto idx : experiment_indices) {
// stat_values.push_back(extract_value(stats_vec[idx]));
stat_values.push_back((stats_vec[idx].*field));
}
// Print min/max/avg and the full sorted contents of `stat_values`.
std::sort(stat_values.begin(), stat_values.end());
os << "min:\t" << stat_values.front() << "\t";
os << "max:\t" << stat_values.back() << "\t";
os << "avg:\t"
<< (std::accumulate(stat_values.begin(), stat_values.end(), 0.) /
static_cast<double>(stat_values.size()))
<< "\t";
os << "--";
for (const auto value : stat_values) {
os << "\t" << value;
}
os << std::endl;
}
}
} // namespace
void PrintExperimentStats(absl::Span<const Stats> stats_vec,
absl::Span<const Environment> env_vec,
std::ostream &os) {
os << "Coverage:\n";
PrintExperimentStatsForOneStatValue(stats_vec, env_vec, os,
&Stats::num_covered_pcs);
os << "Corpus size:\n";
PrintExperimentStatsForOneStatValue(stats_vec, env_vec, os,
&Stats::corpus_size);
os << "Max corpus element size:\n";
PrintExperimentStatsForOneStatValue(stats_vec, env_vec, os,
&Stats::max_corpus_element_size);
os << "Avg corpus element size:\n";
PrintExperimentStatsForOneStatValue(stats_vec, env_vec, os,
&Stats::avg_corpus_element_size);
os << "Number of executions:\n";
PrintExperimentStatsForOneStatValue(stats_vec, env_vec, os,
&Stats::num_executions);
os << "Flags:\n";
absl::flat_hash_set<std::string> printed_names;
for (const auto &env : env_vec) {
if (!printed_names.insert(env.experiment_name).second) continue;
os << env.experiment_name << ": " << env.experiment_flags << "\n";
}
}
void PrintRewardValues(absl::Span<const Stats> stats_vec, std::ostream &os) {
size_t n = stats_vec.size();
CHECK_GT(n, 0);
std::vector<size_t> num_covered_pcs(n);
for (size_t i = 0; i < n; ++i) {
num_covered_pcs[i] = stats_vec[i].num_covered_pcs;
}
std::sort(num_covered_pcs.begin(), num_covered_pcs.end());
os << "REWARD_MAX " << num_covered_pcs.back() << "\n";
os << "REWARD_SECOND_MAX " << num_covered_pcs[n == 1 ? 1 : n - 2] << "\n";
os << "REWARD_MIN " << num_covered_pcs.front() << "\n";
os << "REWARD_MEDIAN " << num_covered_pcs[n / 2] << "\n";
os << "REWARD_AVERAGE "
<< (std::accumulate(num_covered_pcs.begin(), num_covered_pcs.end(), 0.) /
n)
<< "\n";
}
} // namespace centipede