From 592a87b371844731bac6469e8efb6731f102f461 Mon Sep 17 00:00:00 2001 From: mxms Date: Wed, 26 Nov 2025 20:55:18 +0000 Subject: [PATCH 1/7] [ProfData] Improve efficiency of reader Pre-reserve space in the map before inserting. In release builds, 9.4% of all CPU time is spent in llvm::sampleprof::ProfileSymbolList::add. Of that 9.4%, roughly half is in llvm::DenseMapBase::grow. --- llvm/include/llvm/ProfileData/SampleProf.h | 1 + llvm/lib/ProfileData/SampleProf.cpp | 25 +++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index 3dd34aba2d716..6bce5c718e598 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -1658,6 +1658,7 @@ class ProfileSymbolList { } unsigned size() { return Syms.size(); } + void reserve(size_t Size) { Syms.reserve(Size); } void setToCompress(bool TC) { ToCompress = TC; } bool toCompress() { return ToCompress; } diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index ac7513ef2cb49..5f0af79ef33df 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -399,15 +399,30 @@ LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t ListSize) { const char *ListStart = reinterpret_cast(Data); - uint64_t Size = 0; + uint64_t Offset = 0; uint64_t StrNum = 0; - while (Size < ListSize && StrNum < ProfileSymbolListCutOff) { - StringRef Str(ListStart + Size); + uint64_t ExpectedCount = 0; + + Scan forward to see how many elements we expect. + while (Offset < ListSize) { + if (ListStart[Offset] == '\0') ExpectedCount++; + Offset++; + } + + reserve(ExpectedCount); + + Offset = 0; + + while (Offset < ListSize && StrNum < ProfileSymbolListCutOff) { + StringRef Str(ListStart + Offset); add(Str); - Size += Str.size() + 1; + Offset += Str.size() + 1; StrNum++; } - if (Size != ListSize && StrNum != ProfileSymbolListCutOff) + + assert(ExpectedCount == StrNum); + + if (Offset != ListSize && StrNum != ProfileSymbolListCutOff) return sampleprof_error::malformed; return sampleprof_error::success; } From 264d4dda5b2b08838b09d72713008bcb9dff1e29 Mon Sep 17 00:00:00 2001 From: mxms Date: Wed, 26 Nov 2025 20:55:18 +0000 Subject: [PATCH 2/7] [ProfData] Improve efficiency of reader Pre-reserve space in the map before inserting. In release builds, 9.4% of all CPU time is spent in llvm::sampleprof::ProfileSymbolList::add. Of that 9.4%, roughly half is in llvm::DenseMapBase::grow. --- llvm/lib/ProfileData/SampleProf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index 5f0af79ef33df..14f319b3cc28e 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -403,7 +403,7 @@ std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t StrNum = 0; uint64_t ExpectedCount = 0; - Scan forward to see how many elements we expect. + // Scan forward to see how many elements we expect. while (Offset < ListSize) { if (ListStart[Offset] == '\0') ExpectedCount++; Offset++; From 3c994a3b67f631fc9de4194ee573d11d3b1ca904 Mon Sep 17 00:00:00 2001 From: mxms Date: Wed, 26 Nov 2025 20:55:18 +0000 Subject: [PATCH 3/7] [ProfData] Improve efficiency of reader Pre-reserve space in the map before inserting. In release builds, 9.4% of all CPU time is spent in llvm::sampleprof::ProfileSymbolList::add. Of that 9.4%, roughly half is in llvm::DenseMapBase::grow. --- llvm/lib/ProfileData/SampleProf.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index 14f319b3cc28e..17a0e5ba52156 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -399,7 +399,7 @@ LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t ListSize) { const char *ListStart = reinterpret_cast(Data); - uint64_t Offset = 0; + uint64_t Size = 0; uint64_t StrNum = 0; uint64_t ExpectedCount = 0; @@ -407,22 +407,21 @@ std::error_code ProfileSymbolList::read(const uint8_t *Data, while (Offset < ListSize) { if (ListStart[Offset] == '\0') ExpectedCount++; Offset++; - } reserve(ExpectedCount); - Offset = 0; + Size = 0; - while (Offset < ListSize && StrNum < ProfileSymbolListCutOff) { - StringRef Str(ListStart + Offset); + while (Size < ListSize && StrNum < ProfileSymbolListCutOff) { + StringRef Str(ListStart + Size); add(Str); - Offset += Str.size() + 1; + Size += Str.size() + 1; StrNum++; } assert(ExpectedCount == StrNum); - if (Offset != ListSize && StrNum != ProfileSymbolListCutOff) + if (Size != ListSize && StrNum != ProfileSymbolListCutOff) return sampleprof_error::malformed; return sampleprof_error::success; } From 74d52646942ed910aa91245adb3aff4b32ec1e12 Mon Sep 17 00:00:00 2001 From: mxms Date: Wed, 26 Nov 2025 20:55:18 +0000 Subject: [PATCH 4/7] [ProfData] Improve efficiency of reader Pre-reserve space in the map before inserting. In release builds, 9.4% of all CPU time is spent in llvm::sampleprof::ProfileSymbolList::add. Of that 9.4%, roughly half is in llvm::DenseMapBase::grow. --- llvm/lib/ProfileData/SampleProf.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index 17a0e5ba52156..e29fd0811253e 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -404,9 +404,10 @@ std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t ExpectedCount = 0; // Scan forward to see how many elements we expect. - while (Offset < ListSize) { - if (ListStart[Offset] == '\0') ExpectedCount++; - Offset++; + while (Size < ListSize) { + if (ListStart[Size] == '\0') ExpectedCount++; + Size++; + } reserve(ExpectedCount); From abd6ebf5dcddf2e88574027923da207aa1e8c22e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 26 Nov 2025 14:51:46 -0800 Subject: [PATCH 5/7] No assert --- llvm/lib/ProfileData/SampleProf.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index e29fd0811253e..f05a892d5f1fd 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -420,8 +420,6 @@ std::error_code ProfileSymbolList::read(const uint8_t *Data, StrNum++; } - assert(ExpectedCount == StrNum); - if (Size != ListSize && StrNum != ProfileSymbolListCutOff) return sampleprof_error::malformed; return sampleprof_error::success; From 1789f850c361edc0ccc7c00e5d06b6aabec6d086 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 26 Nov 2025 15:01:53 -0800 Subject: [PATCH 6/7] Simplify --- llvm/lib/ProfileData/SampleProf.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index f05a892d5f1fd..e38ff32298dff 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" +#include #include #include @@ -398,28 +399,19 @@ LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t ListSize) { - const char *ListStart = reinterpret_cast(Data); - uint64_t Size = 0; - uint64_t StrNum = 0; - uint64_t ExpectedCount = 0; - // Scan forward to see how many elements we expect. - while (Size < ListSize) { - if (ListStart[Size] == '\0') ExpectedCount++; - Size++; - } - + uint64_t ExpectedCount = std::count(Data, Data + ListSize, 0); reserve(ExpectedCount); - Size = 0; - + const char *ListStart = reinterpret_cast(Data); + uint64_t Size = 0; + uint64_t StrNum = 0; while (Size < ListSize && StrNum < ProfileSymbolListCutOff) { StringRef Str(ListStart + Size); add(Str); Size += Str.size() + 1; StrNum++; } - if (Size != ListSize && StrNum != ProfileSymbolListCutOff) return sampleprof_error::malformed; return sampleprof_error::success; From 711eb400a810f35fd95ec56b3e3a9144553cba71 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 26 Nov 2025 15:03:46 -0800 Subject: [PATCH 7/7] min --- llvm/lib/ProfileData/SampleProf.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index e38ff32298dff..a7d784a72e380 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" #include +#include #include #include @@ -400,8 +401,8 @@ LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } std::error_code ProfileSymbolList::read(const uint8_t *Data, uint64_t ListSize) { // Scan forward to see how many elements we expect. - uint64_t ExpectedCount = std::count(Data, Data + ListSize, 0); - reserve(ExpectedCount); + reserve(std::min(ProfileSymbolListCutOff, + std::count(Data, Data + ListSize, 0))); const char *ListStart = reinterpret_cast(Data); uint64_t Size = 0;