Skip to content

Commit d4ba7ff

Browse files
Print the presence probability when analysis is enabled.
PiperOrigin-RevId: 710098117
1 parent aaa08d8 commit d4ba7ff

File tree

4 files changed

+74
-5
lines changed

4 files changed

+74
-5
lines changed

src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "absl/strings/cord.h"
3333
#include "absl/strings/match.h"
3434
#include "absl/strings/str_cat.h"
35+
#include "absl/strings/str_format.h"
3536
#include "absl/strings/str_replace.h"
3637
#include "absl/strings/string_view.h"
3738
#include "google/protobuf/compiler/cpp/cpp_access_info_parse_helper.h"
@@ -54,6 +55,7 @@ struct PDProtoAnalysis {
5455
PDProtoScale usage = PDProtoScale::kDefault;
5556
uint64_t presence_count = 0;
5657
uint64_t usage_count = 0;
58+
float presence_probability = 0.0;
5759
};
5860

5961
std::ostream& operator<<(std::ostream& s, PDProtoScale scale) {
@@ -119,6 +121,8 @@ class PDProtoAnalyzer {
119121
return analysis;
120122
}
121123

124+
analysis.presence_probability = GetPresenceProbability(field);
125+
122126
if (IsLikelyPresent(field)) {
123127
analysis.presence = PDProtoScale::kLikely;
124128
} else if (IsRarelyPresent(field)) {
@@ -182,6 +186,13 @@ class PDProtoAnalyzer {
182186
info_map_.IsCold(field, AccessInfoMap::kWrite, kColdRatio);
183187
}
184188

189+
float GetPresenceProbability(const FieldDescriptor* field) {
190+
// Since message count is max(#parse, #serialization), return the max of
191+
// access ratio of both parse and serialization.
192+
return std::max(info_map_.AccessRatio(field, AccessInfoMap::kWrite),
193+
info_map_.AccessRatio(field, AccessInfoMap::kRead));
194+
}
195+
185196
cpp::Options options_;
186197
AccessInfoMap info_map_;
187198
SplitMap split_map_;
@@ -436,8 +447,12 @@ static absl::StatusOr<Stats> AnalyzeProfileProto(
436447
stream << " " << TypeName(field) << " " << field->name() << ":";
437448

438449
if (options.print_analysis) {
439-
if (analysis.presence != PDProtoScale::kDefault) {
440-
stream << " " << analysis.presence << "_PRESENT";
450+
if (analysis.presence != PDProtoScale::kDefault ||
451+
options.print_analysis_all) {
452+
stream << " " << analysis.presence << "_PRESENT"
453+
<< absl::StrFormat(
454+
"(%.2f%%)",
455+
analysis.presence_probability * 100);
441456
}
442457
if (analysis.usage != PDProtoScale::kDefault) {
443458
stream << " " << analysis.usage << "_USED("

src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ struct AnalyzeProfileProtoOptions {
2626
// true to include presence and usage info instead of only optimization info
2727
bool print_analysis = false;
2828

29+
// true to include presence probability info
30+
bool print_analysis_all = false;
31+
2932
// Descriptor pool to use. Must not be null.
3033
const DescriptorPool* pool = nullptr;
3134

src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_main.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
ABSL_FLAG(bool, all, false, "Print all fields");
2828
ABSL_FLAG(bool, analysis, false, "Print field analysis");
29+
ABSL_FLAG(bool, analysis_all, false,
30+
"Print detailed field analysis, such as field presence probability, "
31+
"for all fields, not just hot or cold ones.");
2932
ABSL_FLAG(std::string, message_filter, "", "Regex match for message name");
3033
ABSL_FLAG(bool, aggregate_analysis, false,
3134
"If set, will recursively find proto.profile in the given dir and "
@@ -45,6 +48,7 @@ int main(int argc, char* argv[]) {
4548
if (!absl::GetFlag(FLAGS_aggregate_analysis)) {
4649
options.print_all_fields = absl::GetFlag(FLAGS_all);
4750
options.print_analysis = absl::GetFlag(FLAGS_analysis);
51+
options.print_analysis_all = absl::GetFlag(FLAGS_analysis_all);
4852
options.message_filter = absl::GetFlag(FLAGS_message_filter);
4953
status = AnalyzeProfileProtoToText(std::cout, argv[1], options);
5054
} else {

src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.cc

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,9 @@ TEST(AnalyzeProfileProtoTest, PrintStatistics) {
186186
R"(Message google::protobuf::compiler::tools::AnalyzeThis
187187
int32 id: RARELY_USED(100)
188188
string optional_string: RARELY_USED(100)
189-
string[] repeated_string: LIKELY_PRESENT RARELY_USED(100)
190-
AnalyzeChild optional_child: LIKELY_PRESENT RARELY_USED(1) LAZY
191-
AnalyzeChild[] repeated_child: LIKELY_PRESENT RARELY_USED(100)
189+
string[] repeated_string: LIKELY_PRESENT(100.00%) RARELY_USED(100)
190+
AnalyzeChild optional_child: LIKELY_PRESENT(100.00%) RARELY_USED(1) LAZY
191+
AnalyzeChild[] repeated_child: LIKELY_PRESENT(100.00%) RARELY_USED(100)
192192
Nested nested: RARELY_USED(100)
193193
========
194194
singular_lazy_num=1
@@ -209,6 +209,53 @@ repeated_lazy_pcount/repeated_total_pcount=0
209209
)");
210210
}
211211

212+
TEST(AnalyzeProfileProtoTest, PrintStatisticsAll) {
213+
AccessInfo info = ParseTextOrDie(R"pb(
214+
language: "cpp"
215+
message {
216+
name: "google::protobuf::compiler::tools::AnalyzeThis"
217+
count: 100
218+
field { name: "id" getters_count: 1 configs_count: 100 }
219+
field { name: "optional_string" getters_count: 1 configs_count: 100 }
220+
field { name: "optional_child" getters_count: 100 configs_count: 1 }
221+
field { name: "repeated_string" getters_count: 100 configs_count: 100 }
222+
field { name: "repeated_child" getters_count: 100 configs_count: 100 }
223+
field { name: "nested" getters_count: 1 configs_count: 100 }
224+
}
225+
)pb");
226+
AnalyzeProfileProtoOptions options;
227+
options.print_unused_threshold = false;
228+
options.print_optimized = false;
229+
options.print_analysis = true;
230+
options.print_analysis_all = true;
231+
options.pool = DescriptorPool::generated_pool();
232+
EXPECT_STREQ(AnalyzeToText(info, options).c_str(),
233+
R"(Message google::protobuf::compiler::tools::AnalyzeThis
234+
int32 id: DEFAULT_PRESENT(1.00%) RARELY_USED(100)
235+
string optional_string: DEFAULT_PRESENT(1.00%) RARELY_USED(100)
236+
string[] repeated_string: LIKELY_PRESENT(100.00%) RARELY_USED(100)
237+
AnalyzeChild optional_child: LIKELY_PRESENT(100.00%) RARELY_USED(1) LAZY
238+
AnalyzeChild[] repeated_child: LIKELY_PRESENT(100.00%) RARELY_USED(100)
239+
Nested nested: DEFAULT_PRESENT(1.00%) RARELY_USED(100)
240+
========
241+
singular_lazy_num=1
242+
singular_lazy_0usage_num=0
243+
repeated_lazy_num=0
244+
singular_total_pcount=101
245+
repeated_total_pcount=100
246+
singular_lazy_pcount=100
247+
singular_lazy_0usage_pcount=0
248+
repeated_lazy_pcount=0
249+
max_pcount=100
250+
max_ucount=100
251+
repeated_lazy_num/singular_lazy_num=0
252+
repeated_lazy_pcount/singular_lazy_pcount=0
253+
singular_lazy_pcount/singular_total_pcount=0.990099
254+
singular_lazy_0usage_pcount/singular_total_pcount=0
255+
repeated_lazy_pcount/repeated_total_pcount=0
256+
)");
257+
}
258+
212259
} // namespace
213260
} // namespace tools
214261
} // namespace compiler

0 commit comments

Comments
 (0)