-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a library for aggregating branch frequencies from perf data
PiperOrigin-RevId: 700388882
- Loading branch information
1 parent
592c6d8
commit c23b031
Showing
5 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#include "propeller/perf_branch_frequencies_aggregator.h" | ||
|
||
#include <optional> | ||
#include <string> | ||
#include <utility> | ||
|
||
#include "absl/log/log.h" | ||
#include "absl/status/status.h" | ||
#include "absl/status/statusor.h" | ||
#include "propeller/binary_content.h" | ||
#include "propeller/branch_frequencies.h" | ||
#include "propeller/perf_data_provider.h" | ||
#include "propeller/perfdata_reader.h" | ||
#include "propeller/propeller_options.pb.h" | ||
#include "propeller/propeller_statistics.h" | ||
#include "propeller/resolve_mmap_name.h" | ||
#include "propeller/status_macros.h" | ||
|
||
namespace propeller { | ||
|
||
absl::StatusOr<BranchFrequencies> | ||
PerfBranchFrequenciesAggregator::AggregateBranchFrequencies( | ||
const PropellerOptions &options, const BinaryContent &binary_content, | ||
PropellerStats &stats) { | ||
PropellerStats::ProfileStats &profile_stats = stats.profile_stats; | ||
BranchFrequencies frequencies; | ||
|
||
while (true) { | ||
ASSIGN_OR_RETURN(std::optional<PerfDataProvider::BufferHandle> perf_data, | ||
perf_data_provider_->GetNext()); | ||
if (!perf_data.has_value()) break; | ||
|
||
const std::string description = perf_data->description; | ||
LOG(INFO) << "Parsing " << description << " ..."; | ||
absl::StatusOr<PerfDataReader> perf_data_reader = BuildPerfDataReader( | ||
std::move(*perf_data), &binary_content, ResolveMmapName(options)); | ||
if (!perf_data_reader.ok()) { | ||
LOG(WARNING) << "Skipped profile " << description << ": " | ||
<< perf_data_reader.status(); | ||
continue; | ||
} | ||
|
||
profile_stats.binary_mmap_num += perf_data_reader->binary_mmaps().size(); | ||
++profile_stats.perf_file_parsed; | ||
RETURN_IF_ERROR(perf_data_reader->AggregateSpe(frequencies)); | ||
} | ||
profile_stats.br_counters_accumulated += | ||
frequencies.GetNumberOfTakenBranchCounters(); | ||
if (profile_stats.br_counters_accumulated <= 100) | ||
LOG(WARNING) << "Too few branch records in perf data."; | ||
if (profile_stats.perf_file_parsed == 0) { | ||
return absl::FailedPreconditionError( | ||
"No perf file is parsed, cannot proceed."); | ||
} | ||
return frequencies; | ||
} | ||
|
||
} // namespace propeller |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#ifndef PROPELLER_PERF_BRANCH_FREQUENCIES_AGGREGATOR_H_ | ||
#define PROPELLER_PERF_BRANCH_FREQUENCIES_AGGREGATOR_H_ | ||
|
||
#include <memory> | ||
#include <utility> | ||
|
||
#include "absl/status/statusor.h" | ||
#include "propeller/binary_content.h" | ||
#include "propeller/branch_frequencies.h" | ||
#include "propeller/branch_frequencies_aggregator.h" | ||
#include "propeller/perf_data_provider.h" | ||
#include "propeller/propeller_options.pb.h" | ||
#include "propeller/propeller_statistics.h" | ||
|
||
namespace propeller { | ||
// `PerfBranchFrequenciesAggregator` is an implementation of | ||
// `BranchFrequenciesAggregator` that builds `BranchFrequencies` from perf data | ||
// containing SPE entries. The perf data can come from any `PerfDataProvider`, | ||
// such as from a file or mock. | ||
class PerfBranchFrequenciesAggregator : public BranchFrequenciesAggregator { | ||
public: | ||
explicit PerfBranchFrequenciesAggregator( | ||
std::unique_ptr<PerfDataProvider> perf_data_provider) | ||
: perf_data_provider_(std::move(perf_data_provider)) {} | ||
|
||
// PerfBranchFrequenciesAggregator is move-only. | ||
PerfBranchFrequenciesAggregator(PerfBranchFrequenciesAggregator&&) = default; | ||
PerfBranchFrequenciesAggregator& operator=( | ||
PerfBranchFrequenciesAggregator&&) = default; | ||
PerfBranchFrequenciesAggregator(const PerfBranchFrequenciesAggregator&) = | ||
delete; | ||
PerfBranchFrequenciesAggregator& operator=( | ||
const PerfBranchFrequenciesAggregator&) = delete; | ||
|
||
// Aggregates branch frequencies from perf data, may return an `absl::Status` | ||
// if the perf data can't be successfully parsed and aggregated (it doesn't | ||
// exist, is malformed, etc.). | ||
absl::StatusOr<BranchFrequencies> AggregateBranchFrequencies( | ||
const PropellerOptions& options, const BinaryContent& binary_content, | ||
PropellerStats& stats) override; | ||
|
||
private: | ||
std::unique_ptr<PerfDataProvider> perf_data_provider_; | ||
}; | ||
|
||
} // namespace propeller | ||
|
||
#endif // PROPELLER_PERF_BRANCH_FREQUENCIES_AGGREGATOR_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#include "propeller/perf_branch_frequencies_aggregator.h" | ||
|
||
#include <memory> | ||
#include <optional> | ||
#include <string> | ||
#include <string_view> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "propeller/status_testing_macros.h" | ||
#include "gmock/gmock.h" | ||
#include "gtest/gtest.h" | ||
#include "absl/status/status.h" | ||
#include "absl/status/statusor.h" | ||
#include "absl/status/status_matchers.h" | ||
#include "absl/strings/str_cat.h" | ||
#include "propeller/binary_content.h" | ||
#include "propeller/branch_frequencies.h" | ||
#include "propeller/file_perf_data_provider.h" | ||
#include "propeller/perf_data_provider.h" | ||
#include "propeller/propeller_options.pb.h" | ||
#include "propeller/propeller_statistics.h" | ||
|
||
namespace propeller { | ||
namespace { | ||
using ::testing::AllOf; | ||
using ::testing::Field; | ||
using ::testing::SizeIs; | ||
using ::absl_testing::IsOkAndHolds; | ||
using ::absl_testing::StatusIs; | ||
|
||
class MockPerfDataProvider : public PerfDataProvider { | ||
public: | ||
MOCK_METHOD(absl::StatusOr<std::optional<PerfDataProvider::BufferHandle>>, | ||
GetNext, ()); | ||
MOCK_METHOD(absl::StatusOr<std::vector<PerfDataProvider::BufferHandle>>, | ||
GetAllAvailableOrNext, ()); | ||
}; | ||
|
||
static constexpr std::string_view kTestDataDir = | ||
"propeller/testdata/"; | ||
|
||
TEST(PerfBranchFrequenciesAggregator, FailsIfNoPerfData) { | ||
auto mock_perf_data_provider = std::make_unique<MockPerfDataProvider>(); | ||
|
||
// PerfDataProvider::BufferHandle is not copyable, so we can't use | ||
// `testing::Return` here. | ||
EXPECT_CALL(*mock_perf_data_provider, GetNext()).WillRepeatedly([]() { | ||
return absl::InvalidArgumentError("No perf data"); | ||
}); | ||
EXPECT_CALL(*mock_perf_data_provider, GetAllAvailableOrNext()) | ||
.WillRepeatedly( | ||
[]() { return absl::InvalidArgumentError("No perf data"); }); | ||
|
||
PropellerStats stats; | ||
EXPECT_THAT( | ||
PerfBranchFrequenciesAggregator(std::move(mock_perf_data_provider)) | ||
.AggregateBranchFrequencies(PropellerOptions(), BinaryContent(), | ||
stats), | ||
StatusIs(absl::StatusCode::kInvalidArgument)); | ||
} | ||
|
||
} // namespace | ||
} // namespace propeller |