diff --git a/runtime/tests/tooling/sampler/sampling_profiler_test.cpp b/runtime/tests/tooling/sampler/sampling_profiler_test.cpp index 9c3ba11fd0017d2dc8fda6709c9e45bef92fd026..9a9aeb1b2ed0505087917d5237e69f9606d579bf 100644 --- a/runtime/tests/tooling/sampler/sampling_profiler_test.cpp +++ b/runtime/tests/tooling/sampler/sampling_profiler_test.cpp @@ -753,4 +753,34 @@ TEST_F(SamplerTest, ProfilerSamplerSignalHandlerTest) } } +TEST_F(SamplerTest, AsptConverterCalculatePathDepth) +{ + ASSERT_EQ(AsptConverter::CalculatePathDepth("/a"), 1); + ASSERT_EQ(AsptConverter::CalculatePathDepth("a"), 1); + ASSERT_EQ(AsptConverter::CalculatePathDepth("a/"), 1); + ASSERT_EQ(AsptConverter::CalculatePathDepth("/a/b/c/d/"), 4); + ASSERT_EQ(AsptConverter::CalculatePathDepth("a/b/c/d"), 4); +} + +TEST_F(SamplerTest, AsptConverterSubstituteDirectories) +{ + const char *stream_test_filename = "sampler_signal_handler_test.aspt"; + AsptConverter conv(stream_test_filename); + + std::vector src {"/panda/build/pandastdlib", "/runtime/tests/tooling/", "/panda/build", "/panda"}; + std::vector dst {"/panda/build/pstdlib", "/runtime/tests/tling/", "/panda/build", "/pnda"}; + conv.BuildSubstitutionMap(src, dst); + + std::string path_stdlib {"/panda/build/pandastdlib/arkstdlib.abc"}; + std::string path_app {"/panda/build/runtime/tests/tooling/sampler/sampling_profiler_test_ark_asm.abc"}; + conv.SubstituteDirectories(&path_stdlib); + conv.SubstituteDirectories(&path_app); + + std::string expected_path_stdlib {"/panda/build/pstdlib/arkstdlib.abc"}; + std::string expected_path_app {"/panda/build/runtime/tests/tling/sampler/sampling_profiler_test_ark_asm.abc"}; + + ASSERT_EQ(path_stdlib, expected_path_stdlib); + ASSERT_EQ(path_app, expected_path_app); +} + } // namespace panda::tooling::sampler::test diff --git a/tools/sampler/aspt_converter.cpp b/tools/sampler/aspt_converter.cpp index 15edfc19120803b2a1e69fad9f9e7a08b3aa09b0..0127cd75a76b339931dfeb1fa923b13e4cc3727e 100644 --- a/tools/sampler/aspt_converter.cpp +++ b/tools/sampler/aspt_converter.cpp @@ -62,7 +62,7 @@ bool AsptConverter::BuildModulesMap() for (auto &mdl : modules_) { std::string filepath = mdl.pathname; - if (substitute_directories_.has_value()) { + if (!substitution_map_.empty()) { SubstituteDirectories(&filepath); } @@ -87,11 +87,15 @@ bool AsptConverter::BuildModulesMap() void AsptConverter::SubstituteDirectories(std::string *pathname) const { - for (size_t i = 0; i < substitute_directories_->source.size(); ++i) { - auto pos = pathname->find(substitute_directories_->source[i]); - if (pos != std::string::npos) { - pathname->replace(pos, substitute_directories_->source[i].size(), substitute_directories_->destination[i]); - break; + for (const auto &map_it : substitution_map_) { + auto range = substitution_map_.equal_range(map_it.first); + for (auto it = range.first; it != range.second; ++it) { + auto substitute_pair = it->second; + auto pos = pathname->find(substitute_pair.first); + if (pos != std::string::npos) { + pathname->replace(pos, substitute_pair.first.size(), substitute_pair.second); + return; + } } } } @@ -239,10 +243,7 @@ bool AsptConverter::RunWithOptions(const Options &cli_options) build_cold_graph_ = cli_options.IsColdGraphEnable(); if (cli_options.IsSubstituteModuleDir()) { - substitute_directories_ = {cli_options.GetSubstituteSourceStr(), cli_options.GetSubstituteDestinationStr()}; - if (substitute_directories_->source.size() != substitute_directories_->destination.size()) { - LOG(FATAL, PROFILER) << "different number of strings in substitute option"; - } + BuildSubstitutionMap(cli_options.GetSubstituteSourceStr(), cli_options.GetSubstituteDestinationStr()); } if (cli_options.IsDumpModules()) { @@ -252,4 +253,34 @@ bool AsptConverter::RunWithOptions(const Options &cli_options) return RunDumpTracesInCsvMode(outname); } +void AsptConverter::BuildSubstitutionMap(const std::vector &src, const std::vector &dst) +{ + if (src.size() != dst.size()) { + LOG(FATAL, PROFILER) << "different number of strings in substitute option"; + } + + for (size_t i = 0; i < src.size(); ++i) { + if (src[i].empty()) { + LOG(FATAL, PROFILER) << "empty source substitution string"; + } + substitution_map_.insert({CalculatePathDepth(src[i]), std::make_pair(src[i], dst[i])}); + } +} + +size_t AsptConverter::CalculatePathDepth(const std::string &path) +{ + size_t depth = 0; + std::string::size_type pos = 0; + + while (true) { + pos = path.find('/', pos + 1); + if (pos == path.size() - 1 || pos == std::string::npos) { + break; + } + ++depth; + } + + return depth + 1; +} + } // namespace panda::tooling::sampler diff --git a/tools/sampler/aspt_converter.h b/tools/sampler/aspt_converter.h index e6cd3a43f344c3bd9d80d35d1e92a27b7d279f7c..af239cdafbc7e60ccd99ccd3a7f1325493ad85ac 100644 --- a/tools/sampler/aspt_converter.h +++ b/tools/sampler/aspt_converter.h @@ -24,21 +24,15 @@ #include "tools/sampler/trace_dumper.h" #include "tools/sampler/args_parser.h" -#include - namespace panda::tooling::sampler { -struct SubstituteModules { - std::vector source; - std::vector destination; -}; - class AsptConverter { public: NO_COPY_SEMANTIC(AsptConverter); NO_MOVE_SEMANTIC(AsptConverter); using StackTraceMap = std::unordered_map; + using SubstitutionMap = std::multimap, std::greater>; explicit AsptConverter(const char *filename) : reader_(filename) {} ~AsptConverter() = default; @@ -51,6 +45,8 @@ public: void BuildMethodsMap(); + void BuildSubstitutionMap(const std::vector &src, const std::vector &dst); + void SubstituteDirectories(std::string *pathname) const; bool DumpModulesToFile(const std::string &outname) const; @@ -65,6 +61,8 @@ public: static DumpType GetDumpTypeFromOptions(const Options &cli_options); + static size_t CalculatePathDepth(const std::string &path); + private: SampleReader reader_; @@ -77,7 +75,7 @@ private: DumpType dump_type_ {DumpType::THREAD_SEPARATION_BY_TID}; bool build_cold_graph_ {false}; - std::optional substitute_directories_; + SubstitutionMap substitution_map_; }; } // namespace panda::tooling::sampler