• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 //
8 #include "google/protobuf/port.h"
9 
10 #include <cstdio>
11 #include <cstdlib>
12 #include <map>
13 #include <utility>
14 
15 #include "absl/strings/str_format.h"
16 #include "absl/strings/str_split.h"
17 #include "absl/strings/string_view.h"
18 
19 // Must be included last
20 #include "google/protobuf/port_def.inc"
21 
22 namespace google {
23 namespace protobuf {
24 namespace internal {
25 
26 // protobuf_assumption_failed() is declared and used in port_def.inc to assert
27 // PROTOBUF_ASSUME conditions in debug mode. This function avoids having
28 // port_def.inc depend on assert.h or other headers, minimizing the compilation
29 // footprint.
protobuf_assumption_failed(const char * pred,const char * file,int line)30 void protobuf_assumption_failed(const char* pred, const char* file, int line) {
31   fprintf(stderr, "%s: %d: Assumption failed: '%s'\n", file, line, pred);
32   abort();
33 }
34 
35 static void PrintAllCounters();
CounterMap()36 static auto& CounterMap() {
37   using Map = std::map<absl::string_view,
38                        std::map<absl::string_view, const RealDebugCounter*>>;
39   static auto* counter_map = new Map{};
40   static bool dummy = std::atexit(PrintAllCounters);
41   (void)dummy;
42   return *counter_map;
43 }
44 
PrintAllCounters()45 static void PrintAllCounters() {
46   auto& counters = CounterMap();
47   if (counters.empty()) return;
48   absl::FPrintF(stderr, "Protobuf debug counters:\n");
49   for (auto& category : counters) {
50     // Example output:
51     //
52     //   Category  :
53     //     Value 1 : 1234 (12.34%)
54     //     Value 2 : 2345 (23.45%)
55     //     Total   : 3579
56     absl::FPrintF(stderr, "  %-12s:\n", category.first);
57     size_t total = 0;
58     for (auto& count : category.second) {
59       total += count.second->value();
60     }
61     for (auto& count : category.second) {
62       size_t value = count.second->value();
63       absl::FPrintF(stderr, "    %-10s: %10zu", count.first, value);
64       if (total != 0 && category.second.size() > 1) {
65         absl::FPrintF(
66             stderr, " (%5.2f%%)",
67             100. * static_cast<double>(value) / static_cast<double>(total));
68       }
69       absl::FPrintF(stderr, "\n");
70     }
71     if (total != 0 && category.second.size() > 1) {
72       absl::FPrintF(stderr, "    %-10s: %10zu\n", "Total", total);
73     }
74   }
75 }
76 
Register(absl::string_view name)77 void RealDebugCounter::Register(absl::string_view name) {
78   std::pair<absl::string_view, absl::string_view> parts =
79       absl::StrSplit(name, '.');
80   CounterMap()[parts.first][parts.second] = this;
81 }
82 
83 }  // namespace internal
84 }  // namespace protobuf
85 }  // namespace google
86 
87 #include "google/protobuf/port_undef.inc"
88