]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Refactor remaining stats_* functions into Statistics
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 12 Sep 2020 18:41:27 +0000 (20:41 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 14 Sep 2020 17:40:06 +0000 (19:40 +0200)
src/CMakeLists.txt
src/Context.cpp
src/Statistics.cpp
src/Statistics.hpp
src/ccache.cpp
src/cleanup.cpp
src/compress.cpp
src/stats.cpp [deleted file]
src/stats.hpp [deleted file]

index 88736d8cb1e9fbe3391f327adba1b927dd5951ce..775472c7b62b3b3fff1d94beb4f194c89653710a 100644 (file)
@@ -39,7 +39,6 @@ set(
   execute.cpp
   hashutil.cpp
   language.cpp
-  stats.cpp
   version.cpp)
 
 if(INODE_CACHE_SUPPORTED)
index 632750ba2693f1f5a0cf83afd1fd074424e4dde7..31784c1d9337bd066c6faa50c8a91039e6450cb2 100644 (file)
@@ -23,7 +23,6 @@
 #include "SignalHandler.hpp"
 #include "Util.hpp"
 #include "hashutil.hpp"
-#include "stats.hpp"
 
 #include <algorithm>
 #include <string>
index 4d9fd4e9a01328b33f376f4d78194c3e0d29e01c..bfcdd9f475ef814976acd042ae8547a8bdd11b0e 100644 (file)
@@ -19,6 +19,7 @@
 #include "Statistics.hpp"
 
 #include "AtomicFile.hpp"
+#include "Config.hpp"
 #include "Lockfile.hpp"
 #include "Logging.hpp"
 #include "Util.hpp"
@@ -28,6 +29,153 @@ using Logging::log;
 using nonstd::nullopt;
 using nonstd::optional;
 
+const unsigned FLAG_NOZERO = 1; // don't zero with the -z option
+const unsigned FLAG_ALWAYS = 2; // always show, even if zero
+const unsigned FLAG_NEVER = 4;  // never show
+
+using Logging::log;
+using nonstd::nullopt;
+using nonstd::optional;
+
+// Returns a formatted version of a statistics value, or the empty string if the
+// statistics line shouldn't be printed.
+using FormatFunction = std::string (*)(uint64_t value);
+
+static std::string
+format_size(uint64_t size)
+{
+  return fmt::format("{:>11}", Util::format_human_readable_size(size));
+}
+
+static std::string
+format_size_times_1024(uint64_t size)
+{
+  return format_size(size * 1024);
+}
+
+static std::string
+format_timestamp(uint64_t timestamp)
+{
+  if (timestamp > 0) {
+    const auto tm = Util::localtime(timestamp);
+    char buffer[100] = "?";
+    if (tm) {
+      strftime(buffer, sizeof(buffer), "%c", &*tm);
+    }
+    return std::string("    ") + buffer;
+  } else {
+    return {};
+  }
+}
+
+static double
+hit_rate(const Counters& counters)
+{
+  const uint64_t direct = counters.get(Statistic::direct_cache_hit);
+  const uint64_t preprocessed = counters.get(Statistic::preprocessed_cache_hit);
+  const uint64_t hit = direct + preprocessed;
+  const uint64_t miss = counters.get(Statistic::cache_miss);
+  const uint64_t total = hit + miss;
+  return total > 0 ? (100.0 * hit) / total : 0.0;
+}
+
+static std::pair<Counters, time_t>
+collect_counters(const Config& config)
+{
+  Counters counters;
+  uint64_t zero_timestamp = 0;
+  time_t last_updated = 0;
+
+  // Add up the stats in each directory.
+  for (size_t dir = 0; dir <= 0xF; ++dir) {
+    const auto path = fmt::format("{}/{:x}/stats", config.cache_dir(), dir);
+
+    counters.set(Statistic::stats_zeroed_timestamp, 0); // Don't add
+    counters.increment(Statistics::read(path));
+    zero_timestamp =
+      std::max(counters.get(Statistic::stats_zeroed_timestamp), zero_timestamp);
+    last_updated = std::max(last_updated, Stat::stat(path).mtime());
+  }
+
+  counters.set(Statistic::stats_zeroed_timestamp, zero_timestamp);
+  return std::make_pair(counters, last_updated);
+}
+
+namespace {
+
+struct StatisticsField
+{
+  StatisticsField(Statistic statistic,
+                  const char* id,
+                  const char* message,
+                  unsigned flags = 0,
+                  FormatFunction format = nullptr)
+    : statistic(statistic),
+      id(id),
+      message(message),
+      flags(flags),
+      format(format)
+  {
+  }
+
+  const Statistic statistic;
+  const char* const id;        // for --print-stats
+  const char* const message;   // for --show-stats
+  const unsigned flags;        // bitmask of FLAG_* values
+  const FormatFunction format; // nullptr -> use plain integer format
+};
+
+} // namespace
+
+#define STATISTICS_FIELD(id, ...)                                              \
+  {                                                                            \
+    Statistic::id, #id, __VA_ARGS__                                            \
+  }
+
+// Statistics fields in display order.
+const StatisticsField k_statistics_fields[] = {
+  STATISTICS_FIELD(
+    stats_zeroed_timestamp, "stats zeroed", FLAG_ALWAYS, format_timestamp),
+  STATISTICS_FIELD(direct_cache_hit, "cache hit (direct)", FLAG_ALWAYS),
+  STATISTICS_FIELD(
+    preprocessed_cache_hit, "cache hit (preprocessed)", FLAG_ALWAYS),
+  STATISTICS_FIELD(cache_miss, "cache miss", FLAG_ALWAYS),
+  STATISTICS_FIELD(called_for_link, "called for link"),
+  STATISTICS_FIELD(called_for_preprocessing, "called for preprocessing"),
+  STATISTICS_FIELD(multiple_source_files, "multiple source files"),
+  STATISTICS_FIELD(compiler_produced_stdout, "compiler produced stdout"),
+  STATISTICS_FIELD(compiler_produced_no_output, "compiler produced no output"),
+  STATISTICS_FIELD(compiler_produced_empty_output,
+                   "compiler produced empty output"),
+  STATISTICS_FIELD(compile_failed, "compile failed"),
+  STATISTICS_FIELD(internal_error, "ccache internal error"),
+  STATISTICS_FIELD(preprocessor_error, "preprocessor error"),
+  STATISTICS_FIELD(could_not_use_precompiled_header,
+                   "can't use precompiled header"),
+  STATISTICS_FIELD(could_not_use_modules, "can't use modules"),
+  STATISTICS_FIELD(could_not_find_compiler, "couldn't find the compiler"),
+  STATISTICS_FIELD(missing_cache_file, "cache file missing"),
+  STATISTICS_FIELD(bad_compiler_arguments, "bad compiler arguments"),
+  STATISTICS_FIELD(unsupported_source_language, "unsupported source language"),
+  STATISTICS_FIELD(compiler_check_failed, "compiler check failed"),
+  STATISTICS_FIELD(autoconf_test, "autoconf compile/link"),
+  STATISTICS_FIELD(unsupported_compiler_option, "unsupported compiler option"),
+  STATISTICS_FIELD(unsupported_code_directive, "unsupported code directive"),
+  STATISTICS_FIELD(output_to_stdout, "output to stdout"),
+  STATISTICS_FIELD(bad_output_file, "could not write to output file"),
+  STATISTICS_FIELD(no_input_file, "no input file"),
+  STATISTICS_FIELD(error_hashing_extra_file, "error hashing extra file"),
+  STATISTICS_FIELD(cleanups_performed, "cleanups performed", FLAG_ALWAYS),
+  STATISTICS_FIELD(files_in_cache, "files in cache", FLAG_NOZERO | FLAG_ALWAYS),
+  STATISTICS_FIELD(cache_size_kibibyte,
+                   "cache size",
+                   FLAG_NOZERO | FLAG_ALWAYS,
+                   format_size_times_1024),
+  STATISTICS_FIELD(obsolete_max_files, "OBSOLETE", FLAG_NOZERO | FLAG_NEVER),
+  STATISTICS_FIELD(obsolete_max_size, "OBSOLETE", FLAG_NOZERO | FLAG_NEVER),
+  STATISTICS_FIELD(none, nullptr),
+};
+
 namespace Statistics {
 
 Counters
@@ -88,4 +236,118 @@ update(const std::string& path,
   return counters;
 }
 
+optional<std::string>
+get_result(const Counters& counters)
+{
+  for (const auto& field : k_statistics_fields) {
+    if (counters.get(field.statistic) != 0 && !(field.flags & FLAG_NOZERO)) {
+      return field.message;
+    }
+  }
+  return nullopt;
+}
+
+void
+zero_all_counters(const Config& config)
+{
+  const time_t timestamp = time(nullptr);
+
+  for (size_t dir = 0; dir <= 0xF; ++dir) {
+    auto fname = fmt::format("{}/{:x}/stats", config.cache_dir(), dir);
+    if (!Stat::stat(fname)) {
+      // No point in trying to reset the stats file if it doesn't exist.
+      continue;
+    }
+
+    Statistics::update(fname, [=](Counters& cs) {
+      for (size_t i = 0; k_statistics_fields[i].message; ++i) {
+        if (!(k_statistics_fields[i].flags & FLAG_NOZERO)) {
+          cs.set(k_statistics_fields[i].statistic, 0);
+        }
+      }
+      cs.set(Statistic::stats_zeroed_timestamp, timestamp);
+    });
+  }
+}
+
+std::string
+format_human_readable(const Config& config)
+{
+  Counters counters;
+  time_t last_updated;
+  std::tie(counters, last_updated) = collect_counters(config);
+  std::string result;
+
+  result += fmt::format("{:36}{}\n", "cache directory", config.cache_dir());
+  result +=
+    fmt::format("{:36}{}\n", "primary config", config.primary_config_path());
+  result += fmt::format(
+    "{:36}{}\n", "secondary config (readonly)", config.secondary_config_path());
+  if (last_updated > 0) {
+    const auto tm = Util::localtime(last_updated);
+    char timestamp[100] = "?";
+    if (tm) {
+      strftime(timestamp, sizeof(timestamp), "%c", &*tm);
+    }
+    result += fmt::format("{:36}{}\n", "stats updated", timestamp);
+  }
+
+  // ...and display them.
+  for (size_t i = 0; k_statistics_fields[i].message; i++) {
+    const Statistic statistic = k_statistics_fields[i].statistic;
+
+    if (k_statistics_fields[i].flags & FLAG_NEVER) {
+      continue;
+    }
+    if (counters.get(statistic) == 0
+        && !(k_statistics_fields[i].flags & FLAG_ALWAYS)) {
+      continue;
+    }
+
+    const std::string value =
+      k_statistics_fields[i].format
+        ? k_statistics_fields[i].format(counters.get(statistic))
+        : fmt::format("{:8}", counters.get(statistic));
+    if (!value.empty()) {
+      result += fmt::format("{:32}{}\n", k_statistics_fields[i].message, value);
+    }
+
+    if (statistic == Statistic::cache_miss) {
+      double percent = hit_rate(counters);
+      result += fmt::format("{:34}{:6.2f} %\n", "cache hit rate", percent);
+    }
+  }
+
+  if (config.max_files() != 0) {
+    result += fmt::format("{:32}{:8}\n", "max files", config.max_files());
+  }
+  if (config.max_size() != 0) {
+    result += fmt::format(
+      "{:32}{}\n", "max cache size", format_size(config.max_size()));
+  }
+
+  return result;
+}
+
+std::string
+format_machine_readable(const Config& config)
+{
+  Counters counters;
+  time_t last_updated;
+  std::tie(counters, last_updated) = collect_counters(config);
+  std::string result;
+
+  result += fmt::format("stats_updated_timestamp\t{}\n", last_updated);
+
+  for (size_t i = 0; k_statistics_fields[i].message; i++) {
+    if (!(k_statistics_fields[i].flags & FLAG_NEVER)) {
+      result += fmt::format("{}\t{}\n",
+                            k_statistics_fields[i].id,
+                            counters.get(k_statistics_fields[i].statistic));
+    }
+  }
+
+  return result;
+}
+
 } // namespace Statistics
index 9aa0ace680055a6610c7efb53e022b465462824e..61721b462ccad923068740ae1b46fd142d739b42 100644 (file)
@@ -27,6 +27,8 @@
 #include <functional>
 #include <string>
 
+class Config;
+
 // Statistics fields in storage order.
 enum class Statistic {
   none = 0,
@@ -77,4 +79,18 @@ Counters read(const std::string& path);
 nonstd::optional<Counters> update(const std::string& path,
                                   std::function<void(Counters& counters)>);
 
+// Return a human-readable string representing the final ccache result, or
+// nullopt if there was no result.
+nonstd::optional<std::string> get_result(const Counters& counters);
+
+// Zero all statistics counters except those tracking cache size and number of
+// files in the cache.
+void zero_all_counters(const Config& config);
+
+// Format cache statistics in human-readable format.
+std::string format_human_readable(const Config& config);
+
+// Format cache statistics in machine-readable format.
+std::string format_machine_readable(const Config& config);
+
 } // namespace Statistics
index e025cfc1674db713bfd3f032233a53b647fe79e2..bcacf8596692586e6cf26193dbf0cd482f0582a0 100644 (file)
@@ -51,7 +51,6 @@
 #include "execute.hpp"
 #include "hashutil.hpp"
 #include "language.hpp"
-#include "stats.hpp"
 
 #include "third_party/fmt/core.h"
 #include "third_party/nonstd/optional.hpp"
@@ -1909,7 +1908,7 @@ finalize_stats(const Context& ctx)
   }
 
   if (!config.log_file().empty() || config.debug()) {
-    const auto result = stats_get_result(ctx.counter_updates);
+    const auto result = Statistics::get_result(ctx.counter_updates);
     if (result) {
       log("Result: {}", *result);
     }
@@ -2361,7 +2360,7 @@ handle_main_options(int argc, const char* const* argv)
     }
 
     case PRINT_STATS:
-      stats_print(ctx.config);
+      fmt::print(Statistics::format_machine_readable(ctx.config));
       break;
 
     case 'c': // --cleanup
@@ -2440,7 +2439,7 @@ handle_main_options(int argc, const char* const* argv)
       break;
 
     case 's': // --show-stats
-      stats_summary(ctx);
+      fmt::print(Statistics::format_human_readable(ctx.config));
       break;
 
     case 'V': // --version
@@ -2473,7 +2472,7 @@ handle_main_options(int argc, const char* const* argv)
     }
 
     case 'z': // --zero-stats
-      stats_zero(ctx);
+      Statistics::zero_all_counters(ctx.config);
       fmt::print("Statistics zeroed\n");
       break;
 
index f7f465771b9ba5e214476b61e50c127695487b5d..3754c327a25131ddc23b616a0c70988149a135d1 100644 (file)
@@ -24,7 +24,6 @@
 #include "Context.hpp"
 #include "Logging.hpp"
 #include "Util.hpp"
-#include "stats.hpp"
 
 #ifdef INODE_CACHE_SUPPORTED
 #  include "InodeCache.hpp"
index 1326a5fa2bb6eac073bf61e404fe5b94799b2e16..80dc418df3e1c1243f631ad76b7681c932a11c53 100644 (file)
@@ -30,7 +30,6 @@
 #include "StdMakeUnique.hpp"
 #include "ThreadPool.hpp"
 #include "ZstdCompressor.hpp"
-#include "stats.hpp"
 
 #include "third_party/fmt/core.h"
 
diff --git a/src/stats.cpp b/src/stats.cpp
deleted file mode 100644 (file)
index 729ae29..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright (C) 2002-2004 Andrew Tridgell
-// Copyright (C) 2009-2020 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-// Routines to handle the stats files. The stats file is stored one per cache
-// subdirectory to make this more scalable.
-
-#include "stats.hpp"
-
-#include "AtomicFile.hpp"
-#include "Context.hpp"
-#include "Counters.hpp"
-#include "Logging.hpp"
-#include "Statistics.hpp"
-#include "cleanup.hpp"
-#include "hashutil.hpp"
-
-#include "third_party/fmt/core.h"
-#include "third_party/nonstd/optional.hpp"
-
-const unsigned FLAG_NOZERO = 1; // don't zero with the -z option
-const unsigned FLAG_ALWAYS = 2; // always show, even if zero
-const unsigned FLAG_NEVER = 4;  // never show
-
-using Logging::log;
-using nonstd::nullopt;
-using nonstd::optional;
-
-// Returns a formatted version of a statistics value, or the empty string if the
-// statistics line shouldn't be printed.
-using FormatFunction = std::string (*)(uint64_t value);
-
-static std::string format_size_times_1024(uint64_t size);
-static std::string format_timestamp(uint64_t timestamp);
-
-namespace {
-
-struct StatisticsField
-{
-  StatisticsField(Statistic statistic,
-                  const char* id,
-                  const char* message,
-                  unsigned flags = 0,
-                  FormatFunction format = nullptr)
-    : statistic(statistic),
-      id(id),
-      message(message),
-      flags(flags),
-      format(format)
-  {
-  }
-
-  const Statistic statistic;
-  const char* const id;        // for --print-stats
-  const char* const message;   // for --show-stats
-  const unsigned flags;        // bitmask of FLAG_* values
-  const FormatFunction format; // nullptr -> use plain integer format
-};
-
-} // namespace
-
-#define STATISTICS_FIELD(id, ...)                                              \
-  {                                                                            \
-    Statistic::id, #id, __VA_ARGS__                                            \
-  }
-
-// Statistics fields in display order.
-const StatisticsField k_statistics_fields[] = {
-  STATISTICS_FIELD(
-    stats_zeroed_timestamp, "stats zeroed", FLAG_ALWAYS, format_timestamp),
-  STATISTICS_FIELD(direct_cache_hit, "cache hit (direct)", FLAG_ALWAYS),
-  STATISTICS_FIELD(
-    preprocessed_cache_hit, "cache hit (preprocessed)", FLAG_ALWAYS),
-  STATISTICS_FIELD(cache_miss, "cache miss", FLAG_ALWAYS),
-  STATISTICS_FIELD(called_for_link, "called for link"),
-  STATISTICS_FIELD(called_for_preprocessing, "called for preprocessing"),
-  STATISTICS_FIELD(multiple_source_files, "multiple source files"),
-  STATISTICS_FIELD(compiler_produced_stdout, "compiler produced stdout"),
-  STATISTICS_FIELD(compiler_produced_no_output, "compiler produced no output"),
-  STATISTICS_FIELD(compiler_produced_empty_output,
-                   "compiler produced empty output"),
-  STATISTICS_FIELD(compile_failed, "compile failed"),
-  STATISTICS_FIELD(internal_error, "ccache internal error"),
-  STATISTICS_FIELD(preprocessor_error, "preprocessor error"),
-  STATISTICS_FIELD(could_not_use_precompiled_header,
-                   "can't use precompiled header"),
-  STATISTICS_FIELD(could_not_use_modules, "can't use modules"),
-  STATISTICS_FIELD(could_not_find_compiler, "couldn't find the compiler"),
-  STATISTICS_FIELD(missing_cache_file, "cache file missing"),
-  STATISTICS_FIELD(bad_compiler_arguments, "bad compiler arguments"),
-  STATISTICS_FIELD(unsupported_source_language, "unsupported source language"),
-  STATISTICS_FIELD(compiler_check_failed, "compiler check failed"),
-  STATISTICS_FIELD(autoconf_test, "autoconf compile/link"),
-  STATISTICS_FIELD(unsupported_compiler_option, "unsupported compiler option"),
-  STATISTICS_FIELD(unsupported_code_directive, "unsupported code directive"),
-  STATISTICS_FIELD(output_to_stdout, "output to stdout"),
-  STATISTICS_FIELD(bad_output_file, "could not write to output file"),
-  STATISTICS_FIELD(no_input_file, "no input file"),
-  STATISTICS_FIELD(error_hashing_extra_file, "error hashing extra file"),
-  STATISTICS_FIELD(cleanups_performed, "cleanups performed", FLAG_ALWAYS),
-  STATISTICS_FIELD(files_in_cache, "files in cache", FLAG_NOZERO | FLAG_ALWAYS),
-  STATISTICS_FIELD(cache_size_kibibyte,
-                   "cache size",
-                   FLAG_NOZERO | FLAG_ALWAYS,
-                   format_size_times_1024),
-  STATISTICS_FIELD(obsolete_max_files, "OBSOLETE", FLAG_NOZERO | FLAG_NEVER),
-  STATISTICS_FIELD(obsolete_max_size, "OBSOLETE", FLAG_NOZERO | FLAG_NEVER),
-  STATISTICS_FIELD(none, nullptr),
-};
-
-static std::string
-format_size(uint64_t size)
-{
-  return fmt::format("{:>11}", Util::format_human_readable_size(size));
-}
-
-static std::string
-format_size_times_1024(uint64_t size)
-{
-  return format_size(size * 1024);
-}
-
-static std::string
-format_timestamp(uint64_t timestamp)
-{
-  if (timestamp > 0) {
-    auto tm = Util::localtime(timestamp);
-    char buffer[100] = "?";
-    if (tm) {
-      strftime(buffer, sizeof(buffer), "%c", &*tm);
-    }
-    return std::string("    ") + buffer;
-  } else {
-    return {};
-  }
-}
-
-static double
-stats_hit_rate(const Counters& counters)
-{
-  uint64_t direct = counters.get(Statistic::direct_cache_hit);
-  uint64_t preprocessed = counters.get(Statistic::preprocessed_cache_hit);
-  uint64_t hit = direct + preprocessed;
-  uint64_t miss = counters.get(Statistic::cache_miss);
-  uint64_t total = hit + miss;
-  return total > 0 ? (100.0 * hit) / total : 0.0;
-}
-
-static void
-stats_collect(const Config& config, Counters& counters, time_t* last_updated)
-{
-  uint64_t zero_timestamp = 0;
-
-  *last_updated = 0;
-
-  // Add up the stats in each directory.
-  for (size_t dir = 0; dir <= 0xF; ++dir) {
-    const auto path = fmt::format("{}/{:x}/stats", config.cache_dir(), dir);
-
-    counters.set(Statistic::stats_zeroed_timestamp, 0); // Don't add
-    counters.increment(Statistics::read(path));
-    zero_timestamp =
-      std::max(counters.get(Statistic::stats_zeroed_timestamp), zero_timestamp);
-    *last_updated = std::max(*last_updated, Stat::stat(path).mtime());
-  }
-
-  counters.set(Statistic::stats_zeroed_timestamp, zero_timestamp);
-}
-
-// Sum and display the total stats for all cache dirs.
-void
-stats_summary(const Context& ctx)
-{
-  Counters counters;
-  time_t last_updated;
-  stats_collect(ctx.config, counters, &last_updated);
-
-  fmt::print("cache directory                     {}\n",
-             ctx.config.cache_dir());
-  fmt::print("primary config                      {}\n",
-             ctx.config.primary_config_path());
-  fmt::print("secondary config (readonly)         {}\n",
-             ctx.config.secondary_config_path());
-  if (last_updated > 0) {
-    auto tm = Util::localtime(last_updated);
-    char timestamp[100] = "?";
-    if (tm) {
-      strftime(timestamp, sizeof(timestamp), "%c", &*tm);
-    }
-    fmt::print("stats updated                       {}\n", timestamp);
-  }
-
-  // ...and display them.
-  for (size_t i = 0; k_statistics_fields[i].message; i++) {
-    Statistic statistic = k_statistics_fields[i].statistic;
-
-    if (k_statistics_fields[i].flags & FLAG_NEVER) {
-      continue;
-    }
-    if (counters.get(statistic) == 0
-        && !(k_statistics_fields[i].flags & FLAG_ALWAYS)) {
-      continue;
-    }
-
-    std::string value;
-    if (k_statistics_fields[i].format) {
-      value = k_statistics_fields[i].format(counters.get(statistic));
-    } else {
-      value = fmt::format("{:8}", counters.get(statistic));
-    }
-    if (!value.empty()) {
-      fmt::print("{:31} {}\n", k_statistics_fields[i].message, value);
-    }
-
-    if (statistic == Statistic::cache_miss) {
-      double percent = stats_hit_rate(counters);
-      fmt::print("cache hit rate                    {:6.2f} %\n", percent);
-    }
-  }
-
-  if (ctx.config.max_files() != 0) {
-    fmt::print("max files                       {:8}\n",
-               ctx.config.max_files());
-  }
-  if (ctx.config.max_size() != 0) {
-    fmt::print("max cache size                  {}\n",
-               format_size(ctx.config.max_size()));
-  }
-}
-
-// Print machine-parsable (tab-separated) statistics counters.
-void
-stats_print(const Config& config)
-{
-  Counters counters;
-  time_t last_updated;
-  stats_collect(config, counters, &last_updated);
-
-  fmt::print("stats_updated_timestamp\t{}\n", last_updated);
-
-  for (size_t i = 0; k_statistics_fields[i].message; i++) {
-    if (!(k_statistics_fields[i].flags & FLAG_NEVER)) {
-      fmt::print("{}\t{}\n",
-                 k_statistics_fields[i].id,
-                 counters.get(k_statistics_fields[i].statistic));
-    }
-  }
-}
-
-// Zero all the stats structures.
-void
-stats_zero(const Context& ctx)
-{
-  time_t timestamp = time(nullptr);
-
-  for (int dir = 0; dir <= 0xF; dir++) {
-    auto fname = fmt::format("{}/{:x}/stats", ctx.config.cache_dir(), dir);
-    if (!Stat::stat(fname)) {
-      // No point in trying to reset the stats file if it doesn't exist.
-      continue;
-    }
-
-    Statistics::update(fname, [=](Counters& cs) {
-      for (size_t i = 0; k_statistics_fields[i].message; ++i) {
-        if (!(k_statistics_fields[i].flags & FLAG_NOZERO)) {
-          cs.set(k_statistics_fields[i].statistic, 0);
-        }
-      }
-      cs.set(Statistic::stats_zeroed_timestamp, timestamp);
-    });
-  }
-}
-
-optional<std::string>
-stats_get_result(const Counters& counters)
-{
-  for (const auto& field : k_statistics_fields) {
-    if (counters.get(field.statistic) != 0 && !(field.flags & FLAG_NOZERO)) {
-      return field.message;
-    }
-  }
-  return nullopt;
-}
diff --git a/src/stats.hpp b/src/stats.hpp
deleted file mode 100644 (file)
index 69d5a00..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2020 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#pragma once
-
-#include "system.hpp"
-
-#include "Counters.hpp"
-
-#include "third_party/nonstd/optional.hpp"
-
-#include <string>
-
-class Config;
-class Context;
-
-void stats_zero(const Context& ctx);
-void stats_summary(const Context& ctx);
-void stats_print(const Config& config);
-
-nonstd::optional<std::string> stats_get_result(const Counters& counters);