LLVM 22.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/MapVector.h"
16#include "llvm/ADT/StringRef.h"
22#include <cstdint>
23#include <memory>
24#include <set>
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.
121 create(StringRef Filename, SampleProfileFormat 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() {}
133
134protected:
135 SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
136 : OutputStream(std::move(OS)) {}
137
138 /// Write a file header for the profile file.
139 virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0;
140
141 // Write function profiles to the profile file.
142 virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
143
144 std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap,
145 size_t OutputSizeLimit,
146 FunctionPruningStrategy *Strategy);
147
148 /// For writeWithSizeLimit in text mode, each newline takes 1 additional byte
149 /// on Windows when actually written to the file, but not written to a memory
150 /// buffer. This needs to be accounted for when rewriting the profile.
151 size_t LineCount;
152
153 /// Output stream where to emit the profile to.
154 std::unique_ptr<raw_ostream> OutputStream;
155
156 /// Profile summary.
157 std::unique_ptr<ProfileSummary> Summary;
158
159 /// Compute summary for this profile.
160 void computeSummary(const SampleProfileMap &ProfileMap);
161
162 /// Profile format.
164};
165
166/// Sample-based profile writer (text format).
168public:
169 std::error_code writeSample(const FunctionSamples &S) override;
170
171protected:
172 SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
173 : SampleProfileWriter(OS) {}
174
175 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
176 LineCount = 0;
178 }
179
180 void setUseCtxSplitLayout() override {
181 MarkFlatProfiles = true;
182 }
183
184private:
185 /// Indent level to use when writing.
186 ///
187 /// This is used when printing inlined callees.
188 unsigned Indent = 0;
189
190 /// If set, writes metadata "!Flat" to functions without inlined functions.
191 /// This flag is for manual inspection only, it has no effect for the profile
192 /// reader because a text sample profile is read sequentially and functions
193 /// cannot be skipped.
194 bool MarkFlatProfiles = false;
195
197 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
199};
200
201/// Sample-based profile writer (binary format).
203public:
204 SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
205 : SampleProfileWriter(OS) {}
206
207 std::error_code writeSample(const FunctionSamples &S) override;
208
209protected:
211 virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
212 virtual std::error_code writeNameTable();
213 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
214 std::error_code writeSummary();
215 virtual std::error_code writeContextIdx(const SampleContext &Context);
216 std::error_code writeNameIdx(FunctionId FName);
217 std::error_code writeBody(const FunctionSamples &S);
218 inline void stablizeNameTable(MapVector<FunctionId, uint32_t> &NameTable,
219 std::set<FunctionId> &V);
220
222
223 void addName(FunctionId FName);
224 virtual void addContext(const SampleContext &Context);
225 void addNames(const FunctionSamples &S);
226
227 /// Write \p CallsiteTypeMap to the output stream \p OS.
228 std::error_code
230 raw_ostream &OS);
231
232 bool WriteVTableProf = false;
233
234private:
236 SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
238};
239
240class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
242};
243
244const std::array<SmallVector<SecHdrTableEntry, 8>, NumOfLayout>
246 // Note that SecFuncOffsetTable section is written after SecLBRProfile
247 // in the profile, but is put before SecLBRProfile in SectionHdrLayout.
248 // This is because sample reader follows the order in SectionHdrLayout
249 // to read each section. To read function profiles on demand, sample
250 // reader need to get the offset of each function profile first.
251 //
252 // DefaultLayout
254 {SecNameTable, 0, 0, 0, 0},
255 {SecCSNameTable, 0, 0, 0, 0},
256 {SecFuncOffsetTable, 0, 0, 0, 0},
257 {SecLBRProfile, 0, 0, 0, 0},
258 {SecProfileSymbolList, 0, 0, 0, 0},
259 {SecFuncMetadata, 0, 0, 0, 0}}),
260 // CtxSplitLayout
262 {SecNameTable, 0, 0, 0, 0},
263 // profile with inlined functions
264 // for next two sections
265 {SecFuncOffsetTable, 0, 0, 0, 0},
266 {SecLBRProfile, 0, 0, 0, 0},
267 // profile without inlined functions
268 // for next two sections
269 {SecFuncOffsetTable, 0, 0, 0, 0},
270 {SecLBRProfile, 0, 0, 0, 0},
271 {SecProfileSymbolList, 0, 0, 0, 0},
272 {SecFuncMetadata, 0, 0, 0, 0}}),
273};
274
276 : public SampleProfileWriterBinary {
278public:
279 std::error_code write(const SampleProfileMap &ProfileMap) override;
280
281 void setToCompressAllSections() override;
283 std::error_code writeSample(const FunctionSamples &S) override;
284
285 // Set to use MD5 to represent string in NameTable.
286 void setUseMD5() override {
287 UseMD5 = true;
289 // MD5 will be stored as plain uint64_t instead of variable-length
290 // quantity format in NameTable section.
292 }
293
294 // Set the profile to be partial. It means the profile is for
295 // common/shared code. The common profile is usually merged from
296 // profiles collected from running other targets.
300
302 ProfSymList = PSL;
303 };
304
308
310 verifySecLayout(SL);
311#ifndef NDEBUG
312 // Make sure resetSecLayout is called before any flag setting.
313 for (auto &Entry : SectionHdrLayout) {
314 assert(Entry.Flags == 0 &&
315 "resetSecLayout has to be called before any flag setting");
316 }
317#endif
318 SecLayout = SL;
320 }
321
322protected:
323 uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx);
324 std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx,
325 uint64_t SectionStart);
326 template <class SecFlagType>
327 void addSectionFlag(SecType Type, SecFlagType Flag) {
328 for (auto &Entry : SectionHdrLayout) {
329 if (Entry.Type == Type)
330 addSecFlag(Entry, Flag);
331 }
332 }
333 template <class SecFlagType>
334 void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag) {
335 addSecFlag(SectionHdrLayout[SectionIdx], Flag);
336 }
337
338 void addContext(const SampleContext &Context) override;
339
340 // placeholder for subclasses to dispatch their own section writers.
341 virtual std::error_code writeCustomSection(SecType Type) = 0;
342 // Verify the SecLayout is supported by the format.
343 virtual void verifySecLayout(SectionLayout SL) = 0;
344
345 // specify the order to write sections.
346 virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0;
347
348 // Dispatch section writer for each section. \p LayoutIdx is the sequence
349 // number indicating where the section is located in SectionHdrLayout.
350 virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx,
351 const SampleProfileMap &ProfileMap);
352
353 // Helper function to write name table.
354 std::error_code writeNameTable() override;
355 std::error_code writeContextIdx(const SampleContext &Context) override;
356 std::error_code writeCSNameIdx(const SampleContext &Context);
357 std::error_code writeCSNameTableSection();
358
359 std::error_code writeFuncMetadata(const SampleProfileMap &Profiles);
360 std::error_code writeFuncMetadata(const FunctionSamples &Profile);
361
362 // Functions to write various kinds of sections.
363 std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
364 std::error_code writeFuncOffsetTable();
365 std::error_code writeProfileSymbolListSection();
366
368 // Specifiy the order of sections in section header table. Note
369 // the order of sections in SecHdrTable may be different that the
370 // order in SectionHdrLayout. sample Reader will follow the order
371 // in SectionHdrLayout to read each section.
374
375 // Save the start of SecLBRProfile so we can compute the offset to the
376 // start of SecLBRProfile for each Function's Profile and will keep it
377 // in FuncOffsetTable.
379
380private:
381 void allocSecHdrTable();
382 std::error_code writeSecHdrTable();
383 std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
384 std::error_code compressAndOutput();
385
386 // We will swap the raw_ostream held by LocalBufStream and that
387 // held by OutputStream if we try to add a section which needs
388 // compression. After the swap, all the data written to output
389 // will be temporarily buffered into the underlying raw_string_ostream
390 // originally held by LocalBufStream. After the data writing for the
391 // section is completed, compress the data in the local buffer,
392 // swap the raw_ostream back and write the compressed data to the
393 // real output.
394 std::unique_ptr<raw_ostream> LocalBufStream;
395 // The location where the output stream starts.
396 uint64_t FileStart;
397 // The location in the output stream where the SecHdrTable should be
398 // written to.
399 uint64_t SecHdrTableOffset;
400 // The table contains SecHdrTableEntry entries in order of how they are
401 // populated in the writer. It may be different from the order in
402 // SectionHdrLayout which specifies the sequence in which sections will
403 // be read.
404 std::vector<SecHdrTableEntry> SecHdrTable;
405
406 // FuncOffsetTable maps function context to its profile offset in
407 // SecLBRProfile section. It is used to load function profile on demand.
409 // Whether to use MD5 to represent string.
410 bool UseMD5 = false;
411
412 /// CSNameTable maps function context to its offset in SecCSNameTable section.
413 /// The offset will be used everywhere where the context is referenced.
415
416 ProfileSymbolList *ProfSymList = nullptr;
417};
418
421public:
422 SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS);
423
424private:
425 std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
426 std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
427
428 std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
429
430 std::error_code writeCustomSection(SecType Type) override {
432 };
433
434 void verifySecLayout(SectionLayout SL) override {
435 assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
436 "Unsupported layout");
437 }
438};
439
440} // end namespace sampleprof
441} // end namespace llvm
442
443#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
Provides ErrorOr<T> smart pointer.
Load MIR Sample Profile
This file implements a map that provides insertion order iteration.
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:36
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
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:777
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, uint32_t LayoutIdx, 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)
void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag)
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)
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 void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:256
const std::array< SmallVector< SecHdrTableEntry, 8 >, NumOfLayout > ExtBinaryHdrLayoutTable
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
Definition SampleProf.h:199
std::map< LineLocation, TypeCountMap > CallsiteTypeMap
Definition SampleProf.h:768
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:1847
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851