66 using namespace support;
71 for (
const auto &K :
P) {
72 FDOStream.
seek(K.Pos);
73 for (
int I = 0;
I < K.N;
I++)
79 FDOStream.
seek(LastPos);
82 std::string &
Data = SOStream.
str();
83 for (
const auto &K :
P) {
84 for (
int I = 0;
I < K.N;
I++) {
86 endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[
I]);
88 (
const char *)&Bytes,
sizeof(
uint64_t));
122 static std::pair<offset_type, offset_type>
124 using namespace support;
132 for (
const auto &ProfileData : *V) {
141 M += ValueProfData::getSize(ProfileData.second);
145 return std::make_pair(
N, M);
153 using namespace support;
156 for (
const auto &ProfileData : *V) {
163 LE.write<
uint64_t>(ProfileData.first);
173 std::unique_ptr<ValueProfData> VDataPtr =
174 ValueProfData::serializeFrom(ProfileData.second);
177 Out.
write((
const char *)VDataPtr.get(), S);
185 bool Sparse,
uint64_t TemporalProfTraceReservoirSize,
186 uint64_t MaxTemporalProfTraceLength,
bool WritePrevVersion,
188 : Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength),
189 TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize),
191 WritePrevVersion(WritePrevVersion),
192 MemProfVersionRequested(MemProfVersionRequested) {}
202 this->Sparse = Sparse;
217 auto Hash =
Other.Hash;
218 Other.accumulateCounts(FuncLevelOverlap.
Test);
219 if (!FunctionData.contains(
Name)) {
227 auto &ProfileDataMap = FunctionData[
Name];
230 std::tie(Where, NewFunc) =
242 Dest.
overlap(
Other, Overlap, FuncLevelOverlap, ValueCutoff);
248 auto &ProfileDataMap = FunctionData[
Name];
252 std::tie(Where, NewFunc) =
257 Warn(make_error<InstrProfError>(E));
264 Dest.
scale(Weight, 1, MapWarn);
267 Dest.
merge(
I, Weight, MapWarn);
275 auto Result = MemProfRecordData.insert({Id,
Record});
287 auto Result = MemProfFrameData.insert({Id, Frame});
292 if (!Result.second && Result.first->second != Frame) {
294 "frame to id mapping mismatch"));
305 if (
Trace.FunctionNameRefs.
size() > MaxTemporalProfTraceLength)
306 Trace.FunctionNameRefs.resize(MaxTemporalProfTraceLength);
310 if (TemporalProfTraceStreamSize < TemporalProfTraceReservoirSize) {
312 TemporalProfTraces.push_back(std::move(
Trace));
315 std::uniform_int_distribution<uint64_t> Distribution(
316 0, TemporalProfTraceStreamSize);
317 uint64_t RandomIndex = Distribution(RNG);
318 if (RandomIndex < TemporalProfTraces.size())
319 TemporalProfTraces[RandomIndex] = std::move(
Trace);
321 ++TemporalProfTraceStreamSize;
329 (TemporalProfTraceStreamSize > TemporalProfTraceReservoirSize);
330 bool IsSrcSampled = (SrcStreamSize > TemporalProfTraceReservoirSize);
331 if (!IsDestSampled && IsSrcSampled) {
333 std::swap(TemporalProfTraces, SrcTraces);
334 std::swap(TemporalProfTraceStreamSize, SrcStreamSize);
339 for (
auto &
Trace : SrcTraces)
340 addTemporalProfileTrace(std::move(
Trace));
347 std::uniform_int_distribution<uint64_t> Distribution(
348 0, TemporalProfTraceStreamSize);
349 uint64_t RandomIndex = Distribution(RNG);
350 if (RandomIndex < TemporalProfTraces.size())
351 IndicesToReplace.
insert(RandomIndex);
352 ++TemporalProfTraceStreamSize;
362 for (
auto &
I : IPW.FunctionData)
363 for (
auto &Func :
I.getValue())
364 addRecord(
I.getKey(), Func.first, std::move(Func.second), 1, Warn);
366 BinaryIds.reserve(BinaryIds.size() + IPW.BinaryIds.size());
367 for (
auto &
I : IPW.BinaryIds)
371 IPW.TemporalProfTraceStreamSize);
373 MemProfFrameData.reserve(IPW.MemProfFrameData.size());
374 for (
auto &
I : IPW.MemProfFrameData) {
381 MemProfRecordData.reserve(IPW.MemProfRecordData.size());
382 for (
auto &
I : IPW.MemProfRecordData) {
387bool InstrProfWriter::shouldEncodeData(
const ProfilingData &PD) {
390 for (
const auto &Func : PD) {
402 using namespace IndexedInstrProf;
413 for (
unsigned I = 0;
I < Res.size();
I++)
421 for (
const auto Id : Schema)
432 RecordWriter.
Schema = Schema;
434 RecordTableGenerator;
435 for (
auto &[GUID,
Record] : MemProfRecordData) {
437 RecordTableGenerator.insert(GUID,
Record, RecordWriter);
440 MemProfRecordData.
clear();
445 return RecordTableGenerator.
Emit(
OS.OS, RecordWriter);
454 for (
auto &[FrameId, Frame] : MemProfFrameData) {
456 FrameTableGenerator.insert(FrameId, Frame);
459 MemProfFrameData.
clear();
461 return FrameTableGenerator.
Emit(
OS.OS);
483 uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
484 OS.patch({{HeaderUpdatePos, Header, std::size(Header)}});
509 uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
510 OS.patch({{HeaderUpdatePos, Header, std::size(Header)}});
535 switch (MemProfVersionRequested) {
545 return make_error<InstrProfError>(
547 formatv(
"MemProf version {} not supported; "
548 "requires version between {} and {}, inclusive",
554 using namespace IndexedInstrProf;
555 using namespace support;
566 for (
const auto &
I : FunctionData)
567 if (shouldEncodeData(
I.getValue()))
570 for (
const auto &
I : OrderedData)
571 Generator.insert(
I.first,
I.second);
576 Header.Version = WritePrevVersion
584 Header.Version |= VARIANT_MASK_IR_PROF;
586 Header.Version |= VARIANT_MASK_CSIR_PROF;
587 if (
static_cast<bool>(ProfileKind &
589 Header.Version |= VARIANT_MASK_INSTR_ENTRY;
591 Header.Version |= VARIANT_MASK_BYTE_COVERAGE;
593 Header.Version |= VARIANT_MASK_FUNCTION_ENTRY_ONLY;
595 Header.Version |= VARIANT_MASK_MEMPROF;
597 Header.Version |= VARIANT_MASK_TEMPORAL_PROF;
601 Header.HashOffset = 0;
602 Header.MemProfOffset = 0;
603 Header.BinaryIdOffset = 0;
604 Header.TemporalProfTracesOffset = 0;
605 Header.VTableNamesOffset = 0;
609 for (
int I = 0;
I < 4;
I++)
634 if (!WritePrevVersion)
639 uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
642 for (
unsigned I = 0;
I < SummarySize /
sizeof(
uint64_t);
I++)
647 CSSummaryOffset =
OS.
tell();
648 CSSummarySize = SummarySize /
sizeof(
uint64_t);
649 for (
unsigned I = 0;
I < CSSummarySize;
I++)
659 MemProfSectionStart =
OS.
tell();
660 if (
auto E =
writeMemProf(
OS, MemProfRecordData, MemProfFrameData,
661 MemProfVersionRequested))
677 BinaryIds.erase(std::unique(BinaryIds.begin(), BinaryIds.end()),
680 for (
auto BI : BinaryIds) {
682 BinaryIdsSectionSize +=
sizeof(
uint64_t);
687 OS.
write(BinaryIdsSectionSize);
689 for (
auto BI : BinaryIds) {
694 for (
unsigned K = 0;
K < BILen;
K++)
698 for (
unsigned K = 0;
K < PaddingSize;
K++)
704 if (!WritePrevVersion) {
705 std::vector<std::string> VTableNameStrs;
707 VTableNameStrs.push_back(VTableName.str());
709 std::string CompressedVTableNames;
710 if (!VTableNameStrs.empty())
713 CompressedVTableNames))
716 const uint64_t CompressedStringLen = CompressedVTableNames.length();
722 for (
auto &c : CompressedVTableNames)
723 OS.writeByte(
static_cast<uint8_t
>(c));
729 for (
uint64_t K = CompressedStringLen;
K < PaddedLength;
K++)
733 uint64_t TemporalProfTracesSectionStart = 0;
735 TemporalProfTracesSectionStart =
OS.
tell();
736 OS.
write(TemporalProfTraces.size());
737 OS.
write(TemporalProfTraceStreamSize);
738 for (
auto &
Trace : TemporalProfTraces) {
741 for (
auto &NameRef :
Trace.FunctionNameRefs)
747 std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
751 std::unique_ptr<ProfileSummary> PS = ISB.getSummary();
756 std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary =
nullptr;
759 std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary();
764 if (!WritePrevVersion) {
768 {HashTableStartFieldOffset, &HashTableStart, 1},
771 {MemProfSectionOffset, &MemProfSectionStart, 1},
773 {BinaryIdSectionOffset, &BinaryIdSectionStart, 1},
776 {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1},
777 {VTableNamesOffset, &VTableNamesSectionStart, 1},
779 {SummaryOffset,
reinterpret_cast<uint64_t *
>(TheSummary.get()),
780 (
int)(SummarySize /
sizeof(
uint64_t))},
781 {CSSummaryOffset,
reinterpret_cast<uint64_t *
>(TheCSSummary.get()),
782 (
int)CSSummarySize}};
784 OS.patch(PatchItems);
789 {HashTableStartFieldOffset, &HashTableStart, 1},
792 {MemProfSectionOffset, &MemProfSectionStart, 1},
794 {BinaryIdSectionOffset, &BinaryIdSectionStart, 1},
797 {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1},
799 {SummaryOffset,
reinterpret_cast<uint64_t *
>(TheSummary.get()),
800 (
int)(SummarySize /
sizeof(
uint64_t))},
801 {CSSummaryOffset,
reinterpret_cast<uint64_t *
>(TheCSSummary.get()),
802 (
int)CSSummarySize}};
804 OS.patch(PatchItems);
807 for (
const auto &
I : FunctionData)
808 for (
const auto &
F :
I.getValue())
818 return writeImpl(POS);
823 return writeImpl(POS);
837#define VALUE_PROF_KIND(Enumerator, Value, Descr) #Enumerator,
842 for (
uint32_t VK = 0; VK <= IPVK_Last; VK++) {
843 uint32_t NS = Func.getNumValueSites(VK);
847 uint32_t ND = Func.getNumValueDataForSite(VK, S);
848 std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
851 if ((VK != IPVK_IndirectCallTarget && VK != IPVK_VTableTarget) &&
852 !SeenValues.
insert(VD[
I].Value).second)
865 OS <<
"# Func Hash:\n" << Hash <<
"\n";
866 OS <<
"# Num Counters:\n" << Func.Counts.size() <<
"\n";
867 OS <<
"# Counter Values:\n";
871 if (Func.BitmapBytes.size() > 0) {
872 OS <<
"# Num Bitmap Bytes:\n$" << Func.BitmapBytes.size() <<
"\n";
873 OS <<
"# Bitmap Byte Values:\n";
874 for (uint8_t Byte : Func.BitmapBytes) {
882 uint32_t NumValueKinds = Func.getNumValueKinds();
883 if (!NumValueKinds) {
888 OS <<
"# Num Value Kinds:\n" << Func.getNumValueKinds() <<
"\n";
889 for (
uint32_t VK = 0; VK < IPVK_Last + 1; VK++) {
890 uint32_t NS = Func.getNumValueSites(VK);
894 OS <<
"# NumValueSites:\n" << NS <<
"\n";
896 uint32_t ND = Func.getNumValueDataForSite(VK, S);
898 std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
900 if (VK == IPVK_IndirectCallTarget || VK == IPVK_VTableTarget)
902 << VD[
I].Count <<
"\n";
904 OS << VD[
I].Value <<
":" << VD[
I].Count <<
"\n";
915 OS <<
"# CSIR level Instrumentation Flag\n:csir\n";
917 OS <<
"# IR level Instrumentation Flag\n:ir\n";
919 if (
static_cast<bool>(ProfileKind &
921 OS <<
"# Always instrument the function entry block\n:entry_first\n";
923 OS <<
"# Instrument block coverage\n:single_byte_coverage\n";
927 using RecordType = std::pair<StringRef, FuncPair>;
930 for (
const auto &
I : FunctionData) {
931 if (shouldEncodeData(
I.getValue())) {
934 for (
const auto &Func :
I.getValue())
935 OrderedFuncData.
push_back(std::make_pair(
I.getKey(), Func));
939 for (
const auto &VTableName : VTableNames)
947 return std::tie(
A.first,
A.second.first) <
948 std::tie(
B.first,
B.second.first);
951 for (
const auto &record : OrderedFuncData) {
953 const FuncPair &Func = record.second;
957 for (
const auto &record : OrderedFuncData) {
958 const FuncPair &Func = record.second;
968 OS <<
":temporal_prof_traces\n";
969 OS <<
"# Num Temporal Profile Traces:\n" << TemporalProfTraces.
size() <<
"\n";
970 OS <<
"# Temporal Profile Trace Stream Size:\n"
971 << TemporalProfTraceStreamSize <<
"\n";
972 for (
auto &
Trace : TemporalProfTraces) {
973 OS <<
"# Weight:\n" <<
Trace.Weight <<
"\n";
974 for (
auto &NameRef :
Trace.FunctionNameRefs)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static uint64_t writeMemProfRecords(ProfOStream &OS, llvm::MapVector< GlobalValue::GUID, memprof::IndexedMemProfRecord > &MemProfRecordData, memprof::MemProfSchema *Schema)
static Error writeMemProfV1(ProfOStream &OS, llvm::MapVector< GlobalValue::GUID, memprof::IndexedMemProfRecord > &MemProfRecordData, llvm::MapVector< memprof::FrameId, memprof::Frame > &MemProfFrameData)
static Error writeMemProfV0(ProfOStream &OS, llvm::MapVector< GlobalValue::GUID, memprof::IndexedMemProfRecord > &MemProfRecordData, llvm::MapVector< memprof::FrameId, memprof::Frame > &MemProfFrameData)
static uint64_t writeMemProfFrames(ProfOStream &OS, llvm::MapVector< memprof::FrameId, memprof::Frame > &MemProfFrameData)
static Error writeMemProf(ProfOStream &OS, llvm::MapVector< GlobalValue::GUID, memprof::IndexedMemProfRecord > &MemProfRecordData, llvm::MapVector< memprof::FrameId, memprof::Frame > &MemProfFrameData, memprof::IndexedVersion MemProfVersionRequested)
static void setSummary(IndexedInstrProf::Summary *TheSummary, ProfileSummary &PS)
static const char * ValueProfKindStr[]
static void writeMemProfSchema(ProfOStream &OS, const memprof::MemProfSchema &Schema)
Defines facilities for reading and writing on-disk hash tables.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
static std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
const InstrProfWriter::ProfilingData *const data_type_ref
InstrProfSummaryBuilder * SummaryBuilder
llvm::endianness ValueProfDataEndianness
static hash_value_type ComputeHash(key_type_ref K)
InstrProfSummaryBuilder * CSSummaryBuilder
InstrProfRecordWriterTrait()=default
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N)
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
const InstrProfWriter::ProfilingData *const data_type
void addRecord(const InstrProfRecord &)
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
StringRef getFuncOrVarName(uint64_t ValMD5Hash)
Return name of functions or global variables from the name's md5 hash value.
Error addVTableName(StringRef VTableName)
Adds VTableName as a known symbol, and inserts it to a map that tracks all vtable names.
Error addFuncName(StringRef FuncName)
The method name is kept since there are many callers.
StringRef getFuncOrVarNameIfDefined(uint64_t ValMD5Hash)
Just like getFuncOrVarName, except that it will return literal string 'External Symbol' if the functi...
Error write(raw_fd_ostream &OS)
Write the profile to OS.
void addTemporalProfileTraces(SmallVectorImpl< TemporalProfTraceTy > &SrcTraces, uint64_t SrcStreamSize)
Add SrcTraces using reservoir sampling where SrcStreamSize is the total number of temporal profiling ...
void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, const OverlapFuncFilters &FuncFilter)
Error writeText(raw_fd_ostream &OS)
Write the profile in text format to OS.
InstrProfWriter(bool Sparse=false, uint64_t TemporalProfTraceReservoirSize=0, uint64_t MaxTemporalProfTraceLength=0, bool WritePrevVersion=false, memprof::IndexedVersion MemProfVersionRequested=memprof::Version0)
void addBinaryIds(ArrayRef< llvm::object::BuildID > BIs)
void addMemProfRecord(const GlobalValue::GUID Id, const memprof::IndexedMemProfRecord &Record)
Add a memprof record for a function identified by its Id.
static void writeRecordInText(StringRef Name, uint64_t Hash, const InstrProfRecord &Counters, InstrProfSymtab &Symtab, raw_fd_ostream &OS)
Write Record in text format to OS.
void setValueProfDataEndianness(llvm::endianness Endianness)
void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, function_ref< void(Error)> Warn)
Add function counts for the given function.
void mergeRecordsFromWriter(InstrProfWriter &&IPW, function_ref< void(Error)> Warn)
Merge existing function counts from the given writer.
void writeTextTemporalProfTraceData(raw_fd_ostream &OS, InstrProfSymtab &Symtab)
Write temporal profile trace data to the header in text format to OS.
std::unique_ptr< MemoryBuffer > writeBuffer()
Write the profile, returning the raw data. For testing.
bool addMemProfFrame(const memprof::FrameId, const memprof::Frame &F, function_ref< void(Error)> Warn)
Add a memprof frame identified by the hash of the contents of the frame in FrameId.
void setOutputSparse(bool Sparse)
Error validateRecord(const InstrProfRecord &Func)
This class implements a map that also provides access to all stored values in a deterministic order.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Generates an on disk hash table.
offset_type Emit(raw_ostream &Out)
Emit the table to Out, which must not be at offset 0.
void writeByte(uint8_t V)
void patch(ArrayRef< PatchItem > P)
ProfOStream(raw_string_ostream &STR)
support::endian::Writer LE
ProfOStream(raw_fd_ostream &FD)
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
uint64_t getTotalCount() const
uint64_t getMaxCount() const
const SummaryEntryVector & getDetailedSummary()
uint32_t getNumCounts() const
uint64_t getMaxInternalCount() const
uint64_t getMaxFunctionCount() const
uint32_t getNumFunctions() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
iterator_range< StringMapKeyIterator< ValueTy > > keys() const
StringRef - Represent a constant reference to a string, i.e.
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
uint64_t seek(uint64_t off)
Flushes the stream and repositions the underlying file descriptor position to the offset specified fr...
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
uint64_t ComputeHash(StringRef K)
constexpr uint64_t MaximumSupportedVersion
constexpr uint64_t MinimumSupportedVersion
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
void shuffle(Iterator first, Iterator last, RNG &&g)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Error collectGlobalObjectNameStrings(ArrayRef< std::string > NameStrs, bool doCompression, std::string &Result)
Given a vector of strings (names of global objects like functions or, virtual tables) NameStrs,...
@ FunctionEntryInstrumentation
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper object to track which of three possible relocation mechanisms are used for a particular value ...
void set(SummaryFieldKind K, uint64_t V)
void setEntry(uint32_t I, const ProfileSummaryEntry &E)
uint64_t NumSummaryFields
uint64_t NumCutoffEntries
Profiling information for a single function.
std::vector< uint64_t > Counts
void merge(InstrProfRecord &Other, uint64_t Weight, function_ref< void(instrprof_error)> Warn)
Merge the counts in Other into this one.
void overlap(InstrProfRecord &Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff)
Compute the overlap b/w this IntrprofRecord and Other.
void sortValueData()
Sort value profile data (per site) by count.
std::vector< uint8_t > BitmapBytes
void scale(uint64_t N, uint64_t D, function_ref< void(instrprof_error)> Warn)
Scale up profile counts (including value profile data) by a factor of (N / D).
static bool hasCSFlagInHash(uint64_t FuncHash)
const std::string NameFilter
void addOneMismatch(const CountSumOrPercent &MismatchFunc)
CountSumOrPercent Overlap
void addOneUnique(const CountSumOrPercent &UniqueFunc)
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.
Function object to check whether the first component of a container supported by std::get (like std::...
void merge(const IndexedMemProfRecord &Other)
static MemProfSchema getSchema()
Adapter to write values to a stream in a particular byte order.
void write(ArrayRef< value_type > Val)