LLVM 24.0.0git
SampleProfWriter.h
Go to the documentation of this file.
1//===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains definitions needed for writing sample profiles.
10//
11//===----------------------------------------------------------------------===//
12#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
13#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
14
15#include "llvm/ADT/Eytzinger.h"
16#include "llvm/ADT/MapVector.h"
17#include "llvm/ADT/StringRef.h"
23#include <cstdint>
24#include <memory>
25#include <system_error>
26
27namespace llvm {
28namespace sampleprof {
29
32 // The layout splits profile with inlined functions from profile without
33 // inlined functions. When Thinlto is enabled, ThinLTO postlink phase only
34 // has to load profile with inlined functions and can skip the other part.
37};
38
39/// When writing a profile with size limit, user may want to use a different
40/// strategy to reduce function count other than dropping functions with fewest
41/// samples first. In this case a class implementing the same interfaces should
42/// be provided to SampleProfileWriter::writeWithSizeLimit().
44protected:
47
48public:
49 /// \p ProfileMap A reference to the original profile map. It will be modified
50 /// by Erase().
51 /// \p OutputSizeLimit Size limit in bytes of the output profile. This is
52 /// necessary to estimate how many functions to remove.
55
56 virtual ~FunctionPruningStrategy() = default;
57
58 /// SampleProfileWriter::writeWithSizeLimit() calls this after every write
59 /// iteration if the output size still exceeds the limit. This function
60 /// should erase some functions from the profile map so that the writer tries
61 /// to write the profile again with fewer functions. At least 1 entry from the
62 /// profile map must be erased.
63 ///
64 /// \p CurrentOutputSize Number of bytes in the output if current profile map
65 /// is written.
66 virtual void Erase(size_t CurrentOutputSize) = 0;
67};
68
70 std::vector<NameFunctionSamples> SortedFunctions;
71
72public:
74 size_t OutputSizeLimit);
75
76 /// In this default implementation, functions with fewest samples are dropped
77 /// first. Since the exact size of the output cannot be easily calculated due
78 /// to compression, we use a heuristic to remove as many functions as
79 /// necessary but not too many, aiming to minimize the number of write
80 /// iterations.
81 /// Empirically, functions with larger total sample count contain linearly
82 /// more sample entries, meaning it takes linearly more space to write them.
83 /// The cumulative length is therefore quadratic if all functions are sorted
84 /// by total sample count.
85 /// TODO: Find better heuristic.
86 void Erase(size_t CurrentOutputSize) override;
87};
88
89/// Sample-based profile writer. Base class.
91public:
92 virtual ~SampleProfileWriter() = default;
93
94 /// Write sample profiles in \p S.
95 ///
96 /// \returns status code of the file update operation.
97 virtual std::error_code writeSample(const FunctionSamples &S) = 0;
98
99 /// Write all the sample profiles in the given map of samples.
100 ///
101 /// \returns status code of the file update operation.
102 virtual std::error_code write(const SampleProfileMap &ProfileMap);
103
104 /// Write sample profiles up to given size limit, using the pruning strategy
105 /// to drop some functions if necessary.
106 ///
107 /// \returns status code of the file update operation.
108 template <typename FunctionPruningStrategy = DefaultFunctionPruningStrategy>
109 std::error_code writeWithSizeLimit(SampleProfileMap &ProfileMap,
110 size_t OutputSizeLimit) {
111 FunctionPruningStrategy Strategy(ProfileMap, OutputSizeLimit);
112 return writeWithSizeLimitInternal(ProfileMap, OutputSizeLimit, &Strategy);
113 }
114
116
117 /// Profile writer factory.
118 ///
119 /// Create a new file writer based on the value of \p Format.
122
123 /// Create a new stream writer based on the value of \p Format.
124 /// For testing.
126 create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format);
127
129 virtual void setToCompressAllSections() {}
130 virtual void setUseMD5() {}
131 virtual void setPartialProfile() {}
132 virtual void setUseCtxSplitLayout() {}
134 virtual void setUseMD5IndexedTables() {}
135
138 "Unsupported format version");
139 FormatVersion = V;
140 }
142
143protected:
144 SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
145 : OutputStream(std::move(OS)) {}
146
147 /// Write a file header for the profile file.
148 virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0;
149
150 // Write function profiles to the profile file.
151 virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
152
153 std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap,
154 size_t OutputSizeLimit,
155 FunctionPruningStrategy *Strategy);
156
157 /// For writeWithSizeLimit in text mode, each newline takes 1 additional byte
158 /// on Windows when actually written to the file, but not written to a memory
159 /// buffer. This needs to be accounted for when rewriting the profile.
160 size_t LineCount;
161
162 /// Output stream where to emit the profile to.
163 std::unique_ptr<raw_ostream> OutputStream;
164
165 /// Profile summary.
166 std::unique_ptr<ProfileSummary> Summary;
167
168 /// Compute summary for this profile.
169 void computeSummary(const SampleProfileMap &ProfileMap);
170
171 /// Profile format.
173
174 /// Format version to write.
176};
177
178/// Sample-based profile writer (text format).
180public:
181 std::error_code writeSample(const FunctionSamples &S) override;
182
183protected:
184 SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
185 : SampleProfileWriter(OS) {}
186
187 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
188 LineCount = 0;
190 }
191
192 void setUseCtxSplitLayout() override { MarkFlatProfiles = true; }
193
194private:
195 /// Indent level to use when writing.
196 ///
197 /// This is used when printing inlined callees.
198 unsigned Indent = 0;
199
200 /// If set, writes metadata "!Flat" to functions without inlined functions.
201 /// This flag is for manual inspection only, it has no effect for the profile
202 /// reader because a text sample profile is read sequentially and functions
203 /// cannot be skipped.
204 bool MarkFlatProfiles = false;
205
207 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
209};
210
211/// Sample-based profile writer (binary format).
213public:
214 SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
215 : SampleProfileWriter(OS) {}
216
217 std::error_code writeSample(const FunctionSamples &S) override;
218
219protected:
221 virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
222 virtual std::error_code writeNameTable();
223 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
224 std::error_code writeSummary();
225 virtual std::error_code writeContextIdx(const SampleContext &Context);
226 std::error_code writeNameIdx(FunctionId FName);
227 std::error_code writeBody(const FunctionSamples &S);
228
230
231 void addName(FunctionId FName);
232 virtual void addContext(const SampleContext &Context);
233 void addNames(const FunctionSamples &S);
234
235 /// Write \p CallsiteTypeMap to the output stream \p OS.
236 std::error_code
238 raw_ostream &OS);
239
240 bool WriteVTableProf = false;
241
242private:
244 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
246};
247
248class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
250};
251
252const std::array<SmallVector<SecHdrTableEntry, 8>, NumOfLayout>
254 // Note that SecFuncOffsetTable section is written after SecLBRProfile
255 // in the profile, but is put before SecLBRProfile in SectionHdrLayout.
256 // This is because sample reader follows the order in SectionHdrLayout
257 // to read each section. To read function profiles on demand, sample
258 // reader need to get the offset of each function profile first.
259 //
260 // DefaultLayout
262 {SecNameTable, 0, 0, 0, 0},
263 {SecCSNameTable, 0, 0, 0, 0},
264 {SecFuncOffsetTable, 0, 0, 0, 0},
265 {SecLBRProfile, 0, 0, 0, 0},
266 {SecProfileSymbolList, 0, 0, 0, 0},
267 {SecFuncMetadata, 0, 0, 0, 0}}),
268 // CtxSplitLayout
270 {{SecProfSummary, 0, 0, 0, 0},
271 {SecNameTable, 0, 0, 0, 0},
272 // profile with inlined functions
273 // for next two sections
274 {SecFuncOffsetTable, 0, 0, 0, 0},
275 {SecLBRProfile, 0, 0, 0, 0},
276 // profile without inlined functions
277 // for next two sections
279 static_cast<uint64_t>(SecCommonFlags::SecFlagFlat), 0, 0, 0},
281 0, 0, 0},
282 {SecProfileSymbolList, 0, 0, 0, 0},
283 {SecFuncMetadata, 0, 0, 0, 0}}),
284};
285
287 : public SampleProfileWriterBinary {
289
290public:
291 std::error_code write(const SampleProfileMap &ProfileMap) override;
292
293 void setToCompressAllSections() override;
295 std::error_code writeSample(const FunctionSamples &S) override;
296
297 // Set to use MD5 to represent string in NameTable.
298 void setUseMD5() override {
299 UseMD5 = true;
301 // MD5 will be stored as plain uint64_t instead of variable-length
302 // quantity format in NameTable section.
304 }
305
306 // Set the profile to be partial. It means the profile is for
307 // common/shared code. The common profile is usually merged from
308 // profiles collected from running other targets.
312
314 ProfSymList = PSL;
315 };
316
320
321 void setUseMD5ProfileSymbolList() override { UseMD5ProfSymList = true; }
322
323 void setUseMD5IndexedTables() override { UseMD5IndexedTables = true; }
324
326 verifySecLayout(SL);
327#ifndef NDEBUG
328 // Make sure resetSecLayout is called before any flag setting.
329 for (auto &Entry : SectionHdrLayout) {
330 assert(Entry.Flags == 0 &&
331 "resetSecLayout has to be called before any flag setting");
332 }
333#endif
334 SecLayout = SL;
336 }
337
338protected:
339 uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx);
340 std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx,
341 uint64_t SectionStart);
342 template <class SecFlagType>
343 void addSectionFlag(SecType Type, SecFlagType Flag) {
344 for (auto &Entry : SectionHdrLayout) {
345 if (Entry.Type == Type)
346 addSecFlag(Entry, Flag);
347 }
348 }
349 void addContext(const SampleContext &Context) override;
350
351 // placeholder for subclasses to dispatch their own section writers.
352 virtual std::error_code writeCustomSection(SecType Type) = 0;
353 // Verify the SecLayout is supported by the format.
354 virtual void verifySecLayout(SectionLayout SL) = 0;
355
356 // specify the order to write sections.
357 virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0;
358
359 // Find the first unwritten entry in SectionHdrLayout matching Type, returning
360 // its layout index.
362
363 // Dispatch section writer for each section.
364 virtual std::error_code writeOneSection(SecType Type,
365 const SampleProfileMap &ProfileMap);
366
367 // Helper function to write name table.
368 std::error_code writeNameTable() override;
369 std::error_code writeContextIdx(const SampleContext &Context) override;
370 std::error_code writeCSNameIdx(const SampleContext &Context);
371 std::error_code writeCSNameTableSection();
372
373 std::error_code writeFuncMetadata(const SampleProfileMap &Profiles);
374 std::error_code writeFuncMetadata(const FunctionSamples &Profile);
375
376 // Functions to write various kinds of sections.
377 std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
378 std::error_code
380 std::error_code writeFuncOffsetTable(bool IsNested);
381 std::error_code writeEytzingerFuncOffsetTable(bool IsNested);
382 std::error_code writeLegacyFuncOffsetTable();
383 std::error_code writeProfileSymbolListSection();
385 std::error_code writeMD5ProfileSymbolListSection();
386
388 // Specifiy the order of sections in section header table. Note
389 // the order of sections in SecHdrTable may be different that the
390 // order in SectionHdrLayout. sample Reader will follow the order
391 // in SectionHdrLayout to read each section.
394
395 // Save the start of SecLBRProfile so we can compute the offset to the
396 // start of SecLBRProfile for each Function's Profile and will keep it
397 // in FuncOffsetTable.
399
400private:
401 void allocSecHdrTable();
402 std::error_code writeSecHdrTable();
403 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
404 std::error_code compressAndOutput();
405
406 // We will swap the raw_ostream held by LocalBufStream and that
407 // held by OutputStream if we try to add a section which needs
408 // compression. After the swap, all the data written to output
409 // will be temporarily buffered into the underlying raw_string_ostream
410 // originally held by LocalBufStream. After the data writing for the
411 // section is completed, compress the data in the local buffer,
412 // swap the raw_ostream back and write the compressed data to the
413 // real output.
414 std::unique_ptr<raw_ostream> LocalBufStream;
415 // The location where the output stream starts.
416 uint64_t FileStart;
417 // The location in the output stream where the SecHdrTable should be
418 // written to.
419 uint64_t SecHdrTableOffset;
420 // The table contains SecHdrTableEntry entries in order of how they are
421 // populated in the writer. It may be different from the order in
422 // SectionHdrLayout which specifies the sequence in which sections will
423 // be read.
424 std::vector<SecHdrTableEntry> SecHdrTable;
425
426 // FuncOffsetTable maps function context to its profile offset in
427 // SecLBRProfile section. It is used to load function profile on demand.
429 // Whether to use MD5 to represent string.
430 bool UseMD5 = false;
431 // Whether to write the profile symbol list as 64-bit MD5 hashes in Eytzinger
432 // layout.
433 bool UseMD5ProfSymList = false;
434 // Whether to write MD5-based indexed NameTable and parallel FuncOffsetTable
435 // in Eytzinger layout.
436 bool UseMD5IndexedTables = false;
437 size_t NumNested = 0;
438 size_t NumFlat = 0;
439
440 /// CSNameTable maps function context to its offset in SecCSNameTable section.
441 /// The offset will be used everywhere where the context is referenced.
443
444 ProfileSymbolList *ProfSymList = nullptr;
445};
446
449public:
450 SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS);
451
452private:
453 std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
454 std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
455
456 std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
457
458 std::error_code writeCustomSection(SecType Type) override {
460 };
461
462 void verifySecLayout(SectionLayout SL) override {
463 assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
464 "Unsupported layout");
465 }
466};
467
468} // end namespace sampleprof
469} // end namespace llvm
470
471#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
#define LLVM_ABI
Definition Compiler.h:215
Provides ErrorOr<T> smart pointer.
This file defines the EytzingerTableSpan class, a non-owning view of a buffer formatted as a complete...
Load MIR Sample Profile
This file implements a map that provides insertion order iteration.
static constexpr StringLiteral Filename
static void write(bool isBE, void *P, T V)
Represents either an error or a value T.
Definition ErrorOr.h:56
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
DefaultFunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
void Erase(size_t CurrentOutputSize) override
In this default implementation, functions with fewest samples are dropped first.
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
When writing a profile with size limit, user may want to use a different strategy to reduce function ...
virtual void Erase(size_t CurrentOutputSize)=0
SampleProfileWriter::writeWithSizeLimit() calls this after every write iteration if the output size s...
FunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
ProfileMap A reference to the original profile map.
Representation of the samples collected for a function.
Definition SampleProf.h:826
ProfileSymbolList records the list of function symbols shown up in the binary used to generate the pr...
This class provides operator overloads to the map container using MD5 as the key type,...
SampleProfileWriterBinary(std::unique_ptr< raw_ostream > &OS)
virtual void addContext(const SampleContext &Context)
MapVector< FunctionId, uint32_t > NameTable
std::error_code writeCallsiteVTableProf(const CallsiteTypeMap &CallsiteTypeMap, raw_ostream &OS)
Write CallsiteTypeMap to the output stream OS.
virtual MapVector< FunctionId, uint32_t > & getNameTable()
std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap)
SmallVector< SecHdrTableEntry, 8 > SectionHdrLayout
std::error_code writeFuncMetadata(const SampleProfileMap &Profiles)
virtual std::error_code writeCustomSection(SecType Type)=0
virtual std::error_code writeOneSection(SecType Type, const SampleProfileMap &ProfileMap)
std::error_code writeCSNameIdx(const SampleContext &Context)
virtual void verifySecLayout(SectionLayout SL)=0
void setProfileSymbolList(ProfileSymbolList *PSL) override
virtual std::error_code writeSections(const SampleProfileMap &ProfileMap)=0
void addSectionFlag(SecType Type, SecFlagType Flag)
std::error_code writeEytzingerFuncOffsetTable(bool IsNested)
std::error_code writeEytzingerNameTableSection(const SampleProfileMap &ProfileMap)
std::error_code writeContextIdx(const SampleContext &Context) override
std::error_code writeSample(const FunctionSamples &S) override
Write samples of a top-level function to a binary file.
SampleProfileWriterExtBinary(std::unique_ptr< raw_ostream > &OS)
SampleProfileWriterText(std::unique_ptr< raw_ostream > &OS)
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override
Write a file header for the profile file.
std::error_code writeSample(const FunctionSamples &S) override
Write samples to a text file.
SampleProfileWriter(std::unique_ptr< raw_ostream > &OS)
std::unique_ptr< ProfileSummary > Summary
Profile summary.
virtual std::error_code writeSample(const FunctionSamples &S)=0
Write sample profiles in S.
SampleProfileFormat Format
Profile format.
std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap, size_t OutputSizeLimit, FunctionPruningStrategy *Strategy)
void computeSummary(const SampleProfileMap &ProfileMap)
Compute summary for this profile.
virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap)
std::unique_ptr< raw_ostream > OutputStream
Output stream where to emit the profile to.
std::error_code writeWithSizeLimit(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
Write sample profiles up to given size limit, using the pruning strategy to drop some functions if ne...
virtual void setProfileSymbolList(ProfileSymbolList *PSL)
uint64_t FormatVersion
Format version to write.
size_t LineCount
For writeWithSizeLimit in text mode, each newline takes 1 additional byte on Windows when actually wr...
static ErrorOr< std::unique_ptr< SampleProfileWriter > > create(StringRef Filename, SampleProfileFormat Format)
Profile writer factory.
virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap)=0
Write a file header for the profile file.
static bool formatVersionIsSupported(uint64_t Version)
Definition SampleProf.h:132
SortedVectorMap< LineLocation, TypeCountMap, 0 > CallsiteTypeMap
Definition SampleProf.h:818
static void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:292
const std::array< SmallVector< SecHdrTableEntry, 8 >, NumOfLayout > ExtBinaryHdrLayoutTable
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
Definition SampleProf.h:228
static constexpr uint64_t DefaultVersion
Definition SampleProf.h:126
This is an optimization pass for GlobalISel generic memory operations.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878