-
Notifications
You must be signed in to change notification settings - Fork 125
Add profile summary information to GCOV #251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8258d6e
96c7bf8
d123f70
da84bf2
9931071
d25dcf4
b9e980d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,6 +156,26 @@ void AutoFDOProfileWriter::WriteFunctionProfile() { | |
| FileIndexMap file_map; | ||
| StringTableUpdater::Update(*symbol_map_, &string_index_map, &file_map); | ||
|
|
||
| // Write out the GCOV_TAG_AFDO_SUMMARY section. | ||
| if (absl::GetFlag(FLAGS_gcov_version) >= 3) { | ||
| assert(summary != nullptr); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like I accidentally left an assert in here from the first commit that doesn't work anymore. I think it didn't fail to compile because the assert get preprocessed out - the
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Send a PR to cleanup?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PR put up as #261. |
||
| ProfileSummaryInformation info = ProfileSummaryComputer::Compute( | ||
| *symbol_map_, {std::begin(ProfileSummaryInformation::default_cutoffs), | ||
| std::end(ProfileSummaryInformation::default_cutoffs)}); | ||
| gcov_write_unsigned(GCOV_TAG_AFDO_SUMMARY); | ||
| gcov_write_counter(info.total_count_); | ||
| gcov_write_counter(info.max_count_); | ||
| gcov_write_counter(info.max_function_count_); | ||
| gcov_write_counter(info.num_counts_); | ||
| gcov_write_counter(info.num_functions_); | ||
| gcov_write_counter(info.detailed_summaries_.size()); | ||
| for (const auto &detailed_summary : info.detailed_summaries_) { | ||
| gcov_write_unsigned(detailed_summary.cutoff_); | ||
| gcov_write_counter(detailed_summary.min_count_); | ||
| gcov_write_counter(detailed_summary.num_counts_); | ||
| } | ||
| } | ||
|
|
||
| for (auto &name_index : string_index_map) { | ||
| name_index.second = current_name_index++; | ||
| length_4bytes += (name_index.first.size() | ||
|
|
@@ -243,6 +263,89 @@ bool AutoFDOProfileWriter::WriteToFile(const std::string &output_filename) { | |
| return true; | ||
| } | ||
|
|
||
| bool ProfileSummaryInformation::operator==( | ||
| const ProfileSummaryInformation &other) const { | ||
| return total_count_ == other.total_count_ | ||
| && max_count_ == other.max_count_ | ||
| && max_function_count_ == other.max_function_count_ | ||
| && num_counts_ == other.num_counts_ | ||
| && num_functions_ == other.num_functions_ | ||
| && std::equal(detailed_summaries_.begin(), detailed_summaries_.end(), | ||
| other.detailed_summaries_.begin()); | ||
| } | ||
|
|
||
| bool ProfileSummaryInformation::DetailedSummary::operator==( | ||
| const ProfileSummaryInformation::DetailedSummary &other) const { | ||
| return cutoff_ == other.cutoff_ | ||
| && min_count_ == other.min_count_ | ||
| && num_counts_ == other.num_counts_; | ||
| } | ||
|
|
||
| ProfileSummaryComputer::ProfileSummaryComputer() | ||
| : cutoffs_{std::begin(ProfileSummaryInformation::default_cutoffs), | ||
| std::end(ProfileSummaryInformation::default_cutoffs)} {} | ||
|
|
||
| ProfileSummaryComputer::ProfileSummaryComputer(std::vector<uint32_t> cutoffs) | ||
| : cutoffs_{std::move(cutoffs)} {} | ||
|
|
||
| void ProfileSummaryComputer::VisitTopSymbol(const std::string &name, | ||
| const Symbol *node) { | ||
| info_.num_functions_++; | ||
| info_.max_function_count_ = | ||
| std::max(info_.max_function_count_, node->head_count); | ||
| } | ||
|
|
||
| void ProfileSummaryComputer::Visit(const Symbol *node) { | ||
| // There is a slight difference against the values computed by | ||
| // SampleProfileSummaryBuilder/LLVMProfileBuilder as it represents | ||
| // lineno:discriminator pairs as 16:32 bits. This causes line numbers >= | ||
| // UINT16_MAX to be counted incorrectly (see GetLineNumberFromOffset in | ||
| // source_info.h) as they collide with line numbers < UINT16_MAX. This issue | ||
| // is completely avoided here by just not using the offset info at all. | ||
| for (auto &pos_count : node->pos_counts) { | ||
| uint64_t count = pos_count.second.count; | ||
| info_.total_count_ += count; | ||
| info_.max_count_ = std::max(info_.max_count_, count); | ||
| info_.num_counts_++; | ||
| count_frequencies_[count]++; | ||
| } | ||
| } | ||
|
|
||
| void ProfileSummaryComputer::ComputeDetailedSummary() { | ||
| auto iter = count_frequencies_.begin(); | ||
| auto end = count_frequencies_.end(); | ||
|
|
||
| uint32_t counts_seen = 0; | ||
| uint64_t curr_sum = 0; | ||
| uint64_t count = 0; | ||
|
|
||
| for (const uint32_t cutoff : cutoffs_) { | ||
| assert(cutoff <= 999'999); | ||
| constexpr int scale = 1'000'000; | ||
| using uint128_t = unsigned __int128; | ||
| uint128_t desired_count = info_.total_count_; | ||
| desired_count = desired_count * uint128_t(cutoff); | ||
| desired_count = desired_count / uint128_t(scale); | ||
| // This should never fail as cutoff is always <= scale, so | ||
| // (info_.total_count_ * (cutoff / scale)) is always <= info_.total_count_. | ||
| assert(desired_count <= info_.total_count_); | ||
snehasish marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| while (curr_sum < desired_count && iter != end) { | ||
| count = iter->first; | ||
| uint32_t freq = iter->second; | ||
| curr_sum += (count * freq); | ||
| counts_seen += freq; | ||
| iter++; | ||
| } | ||
| // curr_sum is the cumulative sum of frequencies, of which | ||
| // info_.total_count_ is the maximum value (as computed in | ||
| // ProfileSummaryComputer::Visit). Thus, this assertion will only fail if | ||
| // desired_count > info_.total_count_ and the maximum value that curr_sum | ||
| // can sum to is lesser than it. | ||
| assert(curr_sum >= desired_count); | ||
| info_.detailed_summaries_.push_back({cutoff, count, counts_seen}); | ||
| } | ||
| } | ||
|
|
||
| // Debugging support. ProfileDumper emits a detailed dump of the contents | ||
| // of the input profile. | ||
| class ProfileDumper : public SymbolTraverser { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.