29 for (
const auto &
Block : O) {
31 auto &
B = Blocks.back();
52 static Expected<BlockHeader> readBlockHeader(DataExtractor &Extractor,
56 H.Size = Extractor.getU32(&Offset);
57 if (Offset == CurrentOffset)
58 return make_error<StringError>(
59 Twine(
"Error parsing block header size at offset '") +
60 Twine(CurrentOffset) +
"'",
63 H.Number = Extractor.getU32(&Offset);
64 if (Offset == CurrentOffset)
65 return make_error<StringError>(
66 Twine(
"Error parsing block header number at offset '") +
67 Twine(CurrentOffset) +
"'",
70 H.Thread = Extractor.getU64(&Offset);
71 if (Offset == CurrentOffset)
72 return make_error<StringError>(
73 Twine(
"Error parsing block header thread id at offset '") +
74 Twine(CurrentOffset) +
"'",
79 static Expected<std::vector<Profile::FuncID>> readPath(DataExtractor &Extractor,
82 std::vector<Profile::FuncID> Path;
83 auto CurrentOffset =
Offset;
86 FuncId = Extractor.getSigned(&Offset, 4);
87 if (CurrentOffset == Offset)
88 return make_error<StringError>(
89 Twine(
"Error parsing path at offset '") + Twine(CurrentOffset) +
"'",
92 Path.push_back(FuncId);
93 }
while (FuncId != 0);
94 return std::move(Path);
97 static Expected<Profile::Data> readData(DataExtractor &Extractor,
103 auto CurrentOffset =
Offset;
104 D.CallCount = Extractor.getU64(&Offset);
105 if (CurrentOffset == Offset)
106 return make_error<StringError>(
107 Twine(
"Error parsing call counts at offset '") + Twine(CurrentOffset) +
111 D.CumulativeLocalTime = Extractor.getU64(&Offset);
112 if (CurrentOffset == Offset)
113 return make_error<StringError>(
114 Twine(
"Error parsing cumulative local time at offset '") +
115 Twine(CurrentOffset) +
"'",
123 if (
B.PathData.empty())
124 return make_error<StringError>(
125 "Block may not have empty path data.",
128 Blocks.emplace_back(std::move(
B));
133 auto It = PathIDMap.find(P);
134 if (It == PathIDMap.end())
135 return make_error<StringError>(
138 std::vector<Profile::FuncID> Path;
139 for (
auto Node = It->second; Node; Node = Node->Caller)
140 Path.push_back(Node->Func);
141 return std::move(Path);
148 auto RootToLeafPath =
reverse(P);
151 auto It = RootToLeafPath.begin();
152 auto PathRoot = *It++;
154 find_if(Roots, [PathRoot](TrieNode *
N) {
return N->Func == PathRoot; });
157 TrieNode *Node =
nullptr;
158 if (RootIt == Roots.end()) {
159 NodeStorage.emplace_back();
160 Node = &NodeStorage.back();
161 Node->Func = PathRoot;
162 Roots.push_back(Node);
168 while (It != RootToLeafPath.end()) {
169 auto NodeFuncID = *It++;
170 auto CalleeIt =
find_if(Node->Callees, [NodeFuncID](TrieNode *N) {
171 return N->Func == NodeFuncID;
173 if (CalleeIt == Node->Callees.end()) {
174 NodeStorage.emplace_back();
175 auto NewNode = &NodeStorage.back();
176 NewNode->Func = NodeFuncID;
177 NewNode->Caller = Node;
178 Node->Callees.push_back(NewNode);
189 PathIDMap.insert({Node->ID, Node});
197 using PathDataMapPtr = std::unique_ptr<PathDataMap>;
200 ThreadProfileIndexMap ThreadProfileIndex;
202 for (
const auto &
P : {std::ref(L), std::ref(R)})
203 for (
const auto &Block :
P.get()) {
204 ThreadProfileIndexMap::iterator It;
205 std::tie(It, std::ignore) = ThreadProfileIndex.
insert(
206 {Block.Thread, PathDataMapPtr{
new PathDataMap()}});
207 for (
const auto &PathAndData : Block.PathData) {
208 auto &
PathID = PathAndData.first;
209 auto &
Data = PathAndData.second;
212 PathDataMap::iterator PathDataIt;
214 std::tie(PathDataIt, Inserted) = It->second->insert({NewPathID,
Data});
216 auto &ExistingData = PathDataIt->second;
217 ExistingData.CallCount +=
Data.CallCount;
218 ExistingData.CumulativeLocalTime +=
Data.CumulativeLocalTime;
223 for (
const auto &IndexedThreadBlock : ThreadProfileIndex) {
224 PathDataVector PathAndData;
225 PathAndData.reserve(IndexedThreadBlock.second->size());
226 copy(*IndexedThreadBlock.second, std::back_inserter(PathAndData));
228 Merged.
addBlock({IndexedThreadBlock.first, std::move(PathAndData)}));
236 PathDataMap PathData;
238 for (
const auto &
P : {std::ref(L), std::ref(R)})
239 for (
const auto &Block :
P.get())
240 for (
const auto &PathAndData : Block.PathData) {
241 auto &PathId = PathAndData.first;
242 auto &
Data = PathAndData.second;
245 PathDataMap::iterator PathDataIt;
247 std::tie(PathDataIt, Inserted) = PathData.insert({NewPathID,
Data});
249 auto &ExistingData = PathDataIt->second;
250 ExistingData.CallCount +=
Data.CallCount;
251 ExistingData.CumulativeLocalTime +=
Data.CumulativeLocalTime;
256 PathDataVector Block;
257 Block.reserve(PathData.size());
258 copy(PathData, std::back_inserter(Block));
266 return make_error<StringError>(
267 Twine(
"Cannot read profile from '") + Filename +
"'", EC);
271 return make_error<StringError>(
272 Twine(
"Cannot get filesize of '") + Filename +
"'", EC);
276 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
278 return make_error<StringError>(
279 Twine(
"Cannot mmap profile '") + Filename +
"'", EC);
287 while (Offset != MappedFile.
size()) {
288 auto HeaderOrError = readBlockHeader(Extractor, Offset);
290 return HeaderOrError.takeError();
294 const auto &Header = HeaderOrError.get();
297 auto PathOrError = readPath(Extractor, Offset);
299 return PathOrError.takeError();
300 const auto &Path = PathOrError.get();
303 auto DataOrError = readData(Extractor, Offset);
305 return DataOrError.takeError();
306 auto &
Data = DataOrError.get();
310 {{P.internPath(Path), std::move(Data)}}}))
338 for (
const auto &
E : T) {
339 auto &TSD = ThreadStacks[
E.TId];
345 TSD.push_back({
E.TSC,
E.FuncId});
355 while (!TSD.empty()) {
356 auto Top = TSD.back();
362 auto &TPD = ThreadPathData[
E.TId][InternedPath];
364 TPD.CumulativeLocalTime += FunctionLocalTime;
369 if (Top.FuncId ==
E.FuncId)
388 for (
const auto &ThreadPaths : ThreadPathData) {
389 const auto &TID = ThreadPaths.first;
390 const auto &PathsData = ThreadPaths.second;
393 std::vector<std::pair<Profile::PathID, Profile::Data>>(
394 PathsData.begin(), PathsData.end()),
const T & front() const
front - Get the first element.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
This class represents lattice values for constants.
std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
Profile mergeProfilesByStack(const Profile &L, const Profile &R)
This algorithm will merge two Profile instances into a single Profile instance, aggregating blocks by...
This class represents a memory mapped file.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
PathID internPath(ArrayRef< FuncID > P)
The stack represented in |P| must be in stack order (leaf to root).
std::error_code make_error_code(BitcodeError E)
std::error_code file_size(const Twine &Path, uint64_t &Result)
Get file size.
Tagged union holding either a T or a Error.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Expected< std::vector< FuncID > > expandPath(PathID P) const
Provides a sequence of function IDs from a previously interned PathID.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
A Trace object represents the records that have been loaded from XRay log files generated by instrume...
Expected< Profile > profileFromTrace(const Trace &T)
This function takes a Trace and creates a Profile instance from it.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Profile & operator=(Profile &&O) noexcept
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
static ErrorSuccess success()
Create a success value.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Profile instances are thread-compatible.
Profile mergeProfilesByThread(const Profile &L, const Profile &R)
This algorithm will merge two Profile instances into a single Profile instance, aggregating blocks by...
std::enable_if< std::is_unsigned< T >::value, T >::type AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result...
Error addBlock(Block &&B)
Appends a fully-formed Block instance into the Profile.
Expected< Profile > loadProfile(StringRef Filename)
This function will attempt to load an XRay Profiling Mode profile from the provided |Filename|...
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
StringRef - Represent a constant reference to a string, i.e.
OutputIt copy(R &&Range, OutputIt Out)
std::vector< std::pair< PathID, Data > > PathData
bool empty() const
empty - Check if the array is empty.