Skip to content

Commit 981218e

Browse files
committed
Revert "[llvm-profdata] Add option to cap profile output size"
This reverts commit 48f163b.
1 parent 48f163b commit 981218e

File tree

7 files changed

+26
-428
lines changed

7 files changed

+26
-428
lines changed

llvm/include/llvm/ProfileData/SampleProf.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -427,14 +427,6 @@ class SampleRecord {
427427
void print(raw_ostream &OS, unsigned Indent) const;
428428
void dump() const;
429429

430-
bool operator==(const SampleRecord &Other) const {
431-
return NumSamples == Other.NumSamples && CallTargets == Other.CallTargets;
432-
}
433-
434-
bool operator!=(const SampleRecord &Other) const {
435-
return !(*this == Other);
436-
}
437-
438430
private:
439431
uint64_t NumSamples = 0;
440432
CallTargetMap CallTargets;
@@ -1157,21 +1149,6 @@ class FunctionSamples {
11571149
// all the inline instances and names of call targets.
11581150
void findAllNames(DenseSet<StringRef> &NameSet) const;
11591151

1160-
bool operator==(const FunctionSamples &Other) const {
1161-
return (GUIDToFuncNameMap == Other.GUIDToFuncNameMap ||
1162-
(GUIDToFuncNameMap && Other.GUIDToFuncNameMap &&
1163-
*GUIDToFuncNameMap == *Other.GUIDToFuncNameMap)) &&
1164-
FunctionHash == Other.FunctionHash && Context == Other.Context &&
1165-
TotalSamples == Other.TotalSamples &&
1166-
TotalHeadSamples == Other.TotalHeadSamples &&
1167-
BodySamples == Other.BodySamples &&
1168-
CallsiteSamples == Other.CallsiteSamples;
1169-
}
1170-
1171-
bool operator!=(const FunctionSamples &Other) const {
1172-
return !(*this == Other);
1173-
}
1174-
11751152
private:
11761153
/// CFG hash value for the function.
11771154
uint64_t FunctionHash = 0;

llvm/include/llvm/ProfileData/SampleProfWriter.h

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -35,56 +35,6 @@ enum SectionLayout {
3535
NumOfLayout,
3636
};
3737

38-
/// When writing a profile with size limit, user may want to use a different
39-
/// strategy to reduce function count other than dropping functions with fewest
40-
/// samples first. In this case a class implementing the same interfaces should
41-
/// be provided to SampleProfileWriter::writeWithSizeLimit().
42-
class FunctionPruningStrategy {
43-
protected:
44-
SampleProfileMap &ProfileMap;
45-
size_t OutputSizeLimit;
46-
47-
public:
48-
/// \p ProfileMap A reference to the original profile map. It will be modified
49-
/// by Erase().
50-
/// \p OutputSizeLimit Size limit in bytes of the output profile. This is
51-
/// necessary to estimate how many functions to remove.
52-
FunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
53-
: ProfileMap(ProfileMap), OutputSizeLimit(OutputSizeLimit) {}
54-
55-
virtual ~FunctionPruningStrategy() = default;
56-
57-
/// SampleProfileWriter::writeWithSizeLimit() calls this after every write
58-
/// iteration if the output size still exceeds the limit. This function
59-
/// should erase some functions from the profile map so that the writer tries
60-
/// to write the profile again with fewer functions. At least 1 entry from the
61-
/// profile map must be erased.
62-
///
63-
/// \p CurrentOutputSize Number of bytes in the output if current profile map
64-
/// is written.
65-
virtual void Erase(size_t CurrentOutputSize) = 0;
66-
};
67-
68-
class DefaultFunctionPruningStrategy : public FunctionPruningStrategy {
69-
std::vector<NameFunctionSamples> SortedFunctions;
70-
71-
public:
72-
DefaultFunctionPruningStrategy(SampleProfileMap &ProfileMap,
73-
size_t OutputSizeLimit);
74-
75-
/// In this default implementation, functions with fewest samples are dropped
76-
/// first. Since the exact size of the output cannot be easily calculated due
77-
/// to compression, we use a heuristic to remove as many functions as
78-
/// necessary but not too many, aiming to minimize the number of write
79-
/// iterations.
80-
/// Empirically, functions with larger total sample count contain linearly
81-
/// more sample entries, meaning it takes linearly more space to write them.
82-
/// The cumulative length is therefore quadratic if all functions are sorted
83-
/// by total sample count.
84-
/// TODO: Find better heuristic.
85-
void Erase(size_t CurrentOutputSize) override;
86-
};
87-
8838
/// Sample-based profile writer. Base class.
8939
class SampleProfileWriter {
9040
public:
@@ -100,17 +50,6 @@ class SampleProfileWriter {
10050
/// \returns status code of the file update operation.
10151
virtual std::error_code write(const SampleProfileMap &ProfileMap);
10252

103-
/// Write sample profiles up to given size limit, using the pruning strategy
104-
/// to drop some functions if necessary.
105-
///
106-
/// \returns status code of the file update operation.
107-
template <typename FunctionPruningStrategy = DefaultFunctionPruningStrategy>
108-
std::error_code writeWithSizeLimit(SampleProfileMap &ProfileMap,
109-
size_t OutputSizeLimit) {
110-
FunctionPruningStrategy Strategy(ProfileMap, OutputSizeLimit);
111-
return writeWithSizeLimitInternal(ProfileMap, OutputSizeLimit, &Strategy);
112-
}
113-
11453
raw_ostream &getOutputStream() { return *OutputStream; }
11554

11655
/// Profile writer factory.
@@ -140,15 +79,6 @@ class SampleProfileWriter {
14079
// Write function profiles to the profile file.
14180
virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
14281

143-
std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap,
144-
size_t OutputSizeLimit,
145-
FunctionPruningStrategy *Strategy);
146-
147-
/// For writeWithSizeLimit in text mode, each newline takes 1 additional byte
148-
/// on Windows when actually written to the file, but not written to a memory
149-
/// buffer. This needs to be accounted for when rewriting the profile.
150-
size_t LineCount;
151-
15282
/// Output stream where to emit the profile to.
15383
std::unique_ptr<raw_ostream> OutputStream;
15484

@@ -172,7 +102,6 @@ class SampleProfileWriterText : public SampleProfileWriter {
172102
: SampleProfileWriter(OS), Indent(0) {}
173103

174104
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
175-
LineCount = 0;
176105
return sampleprof_error::success;
177106
}
178107

llvm/lib/ProfileData/SampleProfWriter.cpp

Lines changed: 23 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -30,117 +30,16 @@
3030
#include "llvm/Support/MD5.h"
3131
#include "llvm/Support/raw_ostream.h"
3232
#include <algorithm>
33-
#include <cmath>
3433
#include <cstdint>
3534
#include <memory>
3635
#include <set>
3736
#include <system_error>
3837
#include <utility>
3938
#include <vector>
4039

41-
#define DEBUG_TYPE "llvm-profdata"
42-
4340
using namespace llvm;
4441
using namespace sampleprof;
4542

46-
namespace llvm {
47-
namespace support {
48-
namespace endian {
49-
namespace {
50-
51-
// Adapter class to llvm::support::endian::Writer for pwrite().
52-
struct SeekableWriter {
53-
raw_pwrite_stream &OS;
54-
endianness Endian;
55-
SeekableWriter(raw_pwrite_stream &OS, endianness Endian)
56-
: OS(OS), Endian(Endian) {}
57-
58-
template <typename ValueType>
59-
void pwrite(ValueType Val, size_t Offset) {
60-
std::string StringBuf;
61-
raw_string_ostream SStream(StringBuf);
62-
Writer(SStream, Endian).write(Val);
63-
OS.pwrite(StringBuf.data(), StringBuf.size(), Offset);
64-
}
65-
};
66-
67-
} // namespace
68-
} // namespace endian
69-
} // namespace support
70-
} // namespace llvm
71-
72-
DefaultFunctionPruningStrategy::DefaultFunctionPruningStrategy(
73-
SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
74-
: FunctionPruningStrategy(ProfileMap, OutputSizeLimit) {
75-
sortFuncProfiles(ProfileMap, SortedFunctions);
76-
}
77-
78-
void DefaultFunctionPruningStrategy::Erase(size_t CurrentOutputSize) {
79-
double D = (double)OutputSizeLimit / CurrentOutputSize;
80-
size_t NewSize = (size_t)round(ProfileMap.size() * D * D);
81-
size_t NumToRemove = ProfileMap.size() - NewSize;
82-
if (NumToRemove < 1)
83-
NumToRemove = 1;
84-
85-
assert(NumToRemove <= SortedFunctions.size());
86-
llvm::for_each(
87-
llvm::make_range(SortedFunctions.begin() + SortedFunctions.size() -
88-
NumToRemove,
89-
SortedFunctions.end()),
90-
[&](const NameFunctionSamples &E) { ProfileMap.erase(E.first); });
91-
SortedFunctions.resize(SortedFunctions.size() - NumToRemove);
92-
}
93-
94-
std::error_code SampleProfileWriter::writeWithSizeLimitInternal(
95-
SampleProfileMap &ProfileMap, size_t OutputSizeLimit,
96-
FunctionPruningStrategy *Strategy) {
97-
if (OutputSizeLimit == 0)
98-
return write(ProfileMap);
99-
100-
size_t OriginalFunctionCount = ProfileMap.size();
101-
102-
std::unique_ptr<raw_ostream> OriginalOutputStream;
103-
OutputStream.swap(OriginalOutputStream);
104-
105-
size_t IterationCount = 0;
106-
size_t TotalSize;
107-
108-
SmallVector<char> StringBuffer;
109-
do {
110-
StringBuffer.clear();
111-
OutputStream.reset(new raw_svector_ostream(StringBuffer));
112-
if (std::error_code EC = write(ProfileMap))
113-
return EC;
114-
115-
TotalSize = StringBuffer.size();
116-
// On Windows every "\n" is actually written as "\r\n" to disk but not to
117-
// memory buffer, this difference should be added when considering the total
118-
// output size.
119-
#ifdef _WIN32
120-
if (Format == SPF_Text)
121-
TotalSize += LineCount;
122-
#endif
123-
if (TotalSize <= OutputSizeLimit)
124-
break;
125-
126-
Strategy->Erase(TotalSize);
127-
IterationCount++;
128-
} while (ProfileMap.size() != 0);
129-
130-
if (ProfileMap.size() == 0)
131-
return sampleprof_error::too_large;
132-
133-
OutputStream.swap(OriginalOutputStream);
134-
OutputStream->write(StringBuffer.data(), StringBuffer.size());
135-
LLVM_DEBUG(dbgs() << "Profile originally has " << OriginalFunctionCount
136-
<< " functions, reduced to " << ProfileMap.size() << " in "
137-
<< IterationCount << " iterations\n");
138-
// Silence warning on Release build.
139-
(void)OriginalFunctionCount;
140-
(void)IterationCount;
141-
return sampleprof_error::success;
142-
}
143-
14443
std::error_code
14544
SampleProfileWriter::writeFuncProfiles(const SampleProfileMap &ProfileMap) {
14645
std::vector<NameFunctionSamples> V;
@@ -217,12 +116,6 @@ std::error_code SampleProfileWriterExtBinaryBase::addNewSection(
217116

218117
std::error_code
219118
SampleProfileWriterExtBinaryBase::write(const SampleProfileMap &ProfileMap) {
220-
// When calling write on a different profile map, existing states should be
221-
// cleared.
222-
NameTable.clear();
223-
CSNameTable.clear();
224-
SecHdrTable.clear();
225-
226119
if (std::error_code EC = writeHeader(ProfileMap))
227120
return EC;
228121

@@ -584,7 +477,6 @@ std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
584477
if (Indent == 0)
585478
OS << ":" << S.getHeadSamples();
586479
OS << "\n";
587-
LineCount++;
588480

589481
SampleSorter<LineLocation, SampleRecord> SortedSamples(S.getBodySamples());
590482
for (const auto &I : SortedSamples.get()) {
@@ -601,7 +493,6 @@ std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
601493
for (const auto &J : Sample.getSortedCallTargets())
602494
OS << " " << J.first << ":" << J.second;
603495
OS << "\n";
604-
LineCount++;
605496
}
606497

607498
SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples(
@@ -624,13 +515,11 @@ std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
624515
if (FunctionSamples::ProfileIsProbeBased) {
625516
OS.indent(Indent + 1);
626517
OS << "!CFGChecksum: " << S.getFunctionHash() << "\n";
627-
LineCount++;
628518
}
629519

630520
if (S.getContext().getAllAttributes()) {
631521
OS.indent(Indent + 1);
632522
OS << "!Attributes: " << S.getContext().getAllAttributes() << "\n";
633-
LineCount++;
634523
}
635524

636525
return sampleprof_error::success;
@@ -716,10 +605,14 @@ std::error_code SampleProfileWriterCompactBinary::writeFuncOffsetTable() {
716605
auto &OS = *OutputStream;
717606

718607
// Fill the slot remembered by TableOffset with the offset of FuncOffsetTable.
608+
auto &OFS = static_cast<raw_fd_ostream &>(OS);
719609
uint64_t FuncOffsetTableStart = OS.tell();
720-
support::endian::SeekableWriter Writer(static_cast<raw_pwrite_stream &>(OS),
721-
support::little);
722-
Writer.pwrite(FuncOffsetTableStart, TableOffset);
610+
if (OFS.seek(TableOffset) == (uint64_t)-1)
611+
return sampleprof_error::ostream_seek_unsupported;
612+
support::endian::Writer Writer(*OutputStream, support::little);
613+
Writer.write(FuncOffsetTableStart);
614+
if (OFS.seek(FuncOffsetTableStart) == (uint64_t)-1)
615+
return sampleprof_error::ostream_seek_unsupported;
723616

724617
// Write out the table size.
725618
encodeULEB128(FuncOffsetTable.size(), OS);
@@ -730,7 +623,6 @@ std::error_code SampleProfileWriterCompactBinary::writeFuncOffsetTable() {
730623
return EC;
731624
encodeULEB128(Entry.second, OS);
732625
}
733-
FuncOffsetTable.clear();
734626
return sampleprof_error::success;
735627
}
736628

@@ -758,10 +650,6 @@ SampleProfileWriterBinary::writeMagicIdent(SampleProfileFormat Format) {
758650

759651
std::error_code
760652
SampleProfileWriterBinary::writeHeader(const SampleProfileMap &ProfileMap) {
761-
// When calling write on a different profile map, existing names should be
762-
// cleared.
763-
NameTable.clear();
764-
765653
writeMagicIdent(Format);
766654

767655
computeSummary(ProfileMap);
@@ -802,6 +690,14 @@ void SampleProfileWriterExtBinaryBase::allocSecHdrTable() {
802690
}
803691

804692
std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
693+
auto &OFS = static_cast<raw_fd_ostream &>(*OutputStream);
694+
uint64_t Saved = OutputStream->tell();
695+
696+
// Set OutputStream to the location saved in SecHdrTableOffset.
697+
if (OFS.seek(SecHdrTableOffset) == (uint64_t)-1)
698+
return sampleprof_error::ostream_seek_unsupported;
699+
support::endian::Writer Writer(*OutputStream, support::little);
700+
805701
assert(SecHdrTable.size() == SectionHdrLayout.size() &&
806702
"SecHdrTable entries doesn't match SectionHdrLayout");
807703
SmallVector<uint32_t, 16> IndexMap(SecHdrTable.size(), -1);
@@ -818,23 +714,21 @@ std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
818714
// needs to be computed after SecLBRProfile (the order in SecHdrTable),
819715
// but it needs to be read before SecLBRProfile (the order in
820716
// SectionHdrLayout). So we use IndexMap above to switch the order.
821-
support::endian::SeekableWriter Writer(
822-
static_cast<raw_pwrite_stream &>(*OutputStream), support::little);
823717
for (uint32_t LayoutIdx = 0; LayoutIdx < SectionHdrLayout.size();
824718
LayoutIdx++) {
825719
assert(IndexMap[LayoutIdx] < SecHdrTable.size() &&
826720
"Incorrect LayoutIdx in SecHdrTable");
827721
auto Entry = SecHdrTable[IndexMap[LayoutIdx]];
828-
Writer.pwrite(static_cast<uint64_t>(Entry.Type),
829-
SecHdrTableOffset + 4 * LayoutIdx * sizeof(uint64_t));
830-
Writer.pwrite(static_cast<uint64_t>(Entry.Flags),
831-
SecHdrTableOffset + (4 * LayoutIdx + 1) * sizeof(uint64_t));
832-
Writer.pwrite(static_cast<uint64_t>(Entry.Offset),
833-
SecHdrTableOffset + (4 * LayoutIdx + 2) * sizeof(uint64_t));
834-
Writer.pwrite(static_cast<uint64_t>(Entry.Size),
835-
SecHdrTableOffset + (4 * LayoutIdx + 3) * sizeof(uint64_t));
722+
Writer.write(static_cast<uint64_t>(Entry.Type));
723+
Writer.write(static_cast<uint64_t>(Entry.Flags));
724+
Writer.write(static_cast<uint64_t>(Entry.Offset));
725+
Writer.write(static_cast<uint64_t>(Entry.Size));
836726
}
837727

728+
// Reset OutputStream.
729+
if (OFS.seek(Saved) == (uint64_t)-1)
730+
return sampleprof_error::ostream_seek_unsupported;
731+
838732
return sampleprof_error::success;
839733
}
840734

0 commit comments

Comments
 (0)