@@ -60,14 +60,25 @@ void DataAggregator::findPerfExecutable() {
60
60
61
61
void DataAggregator::start (StringRef PerfDataFilename) {
62
62
Enabled = true ;
63
+ this ->PerfDataFilename = PerfDataFilename;
63
64
outs () << " PERF2BOLT: Starting data aggregation job for " << PerfDataFilename
64
65
<< " \n " ;
65
66
findPerfExecutable ();
66
- launchPerfEventsNoWait (PerfDataFilename );
67
- launchPerfTasksNoWait (PerfDataFilename );
67
+ launchPerfEventsNoWait ();
68
+ launchPerfTasksNoWait ();
68
69
}
69
70
70
- bool DataAggregator::launchPerfEventsNoWait (StringRef PerfDataFilename) {
71
+ void DataAggregator::abort () {
72
+ std::string Error;
73
+
74
+ // Kill subprocesses in case they are not finished
75
+ sys::Wait (TasksPI, 1 , false , &Error);
76
+ sys::Wait (EventsPI, 1 , false , &Error);
77
+
78
+ deleteTempFiles ();
79
+ }
80
+
81
+ bool DataAggregator::launchPerfEventsNoWait () {
71
82
SmallVector<const char *, 4 > Argv;
72
83
SmallVector<StringRef, 3 > Redirects;
73
84
SmallVector<const StringRef*, 3 > RedirectPtrs;
@@ -112,7 +123,7 @@ bool DataAggregator::launchPerfEventsNoWait(StringRef PerfDataFilename) {
112
123
return true ;
113
124
}
114
125
115
- bool DataAggregator::launchPerfTasksNoWait (StringRef PerfDataFilename ) {
126
+ bool DataAggregator::launchPerfTasksNoWait () {
116
127
SmallVector<const char *, 4 > Argv;
117
128
SmallVector<StringRef, 3 > Redirects;
118
129
SmallVector<const StringRef*, 3 > RedirectPtrs;
@@ -156,6 +167,88 @@ bool DataAggregator::launchPerfTasksNoWait(StringRef PerfDataFilename) {
156
167
return true ;
157
168
}
158
169
170
+ Optional<std::string> DataAggregator::getPerfBuildID () {
171
+ SmallVector<const char *, 4 > Argv;
172
+ SmallVector<StringRef, 3 > Redirects;
173
+ SmallVector<const StringRef*, 3 > RedirectPtrs;
174
+ SmallVector<char , 256 > OutputPath;
175
+ SmallVector<char , 256 > ErrPath;
176
+
177
+ Argv.push_back (PerfPath.data ());
178
+ Argv.push_back (" buildid-list" );
179
+ Argv.push_back (" -i" );
180
+ Argv.push_back (PerfDataFilename.data ());
181
+ Argv.push_back (nullptr );
182
+
183
+ if (auto Errc = sys::fs::createTemporaryFile (" perf.buildid" , " out" ,
184
+ OutputPath)) {
185
+ outs () << " PERF2BOLT: Failed to create temporary file "
186
+ << OutputPath << " with error " << Errc.message () << " \n " ;
187
+ exit (1 );
188
+ }
189
+
190
+ if (auto Errc = sys::fs::createTemporaryFile (" perf.script" , " err" ,
191
+ ErrPath)) {
192
+ outs () << " PERF2BOLT: Failed to create temporary file "
193
+ << ErrPath << " with error " << Errc.message () << " \n " ;
194
+ exit (1 );
195
+ }
196
+
197
+ Redirects.push_back (" " ); // Stdin
198
+ Redirects.push_back (StringRef (OutputPath.data ())); // Stdout
199
+ Redirects.push_back (StringRef (ErrPath.data ())); // Stderr
200
+ RedirectPtrs.push_back (&Redirects[0 ]);
201
+ RedirectPtrs.push_back (&Redirects[1 ]);
202
+ RedirectPtrs.push_back (&Redirects[2 ]);
203
+
204
+ DEBUG (dbgs () << " Launching perf: " << PerfPath.data () << " 1> "
205
+ << OutputPath.data () << " 2> "
206
+ << ErrPath.data () << " \n " );
207
+
208
+ auto RetCode = sys::ExecuteAndWait (PerfPath.data (), Argv.data (),
209
+ /* envp*/ nullptr , &RedirectPtrs[0 ]);
210
+
211
+ if (RetCode != 0 ) {
212
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
213
+ MemoryBuffer::getFileOrSTDIN (ErrPath.data ());
214
+ StringRef ErrBuf = (*MB)->getBuffer ();
215
+
216
+ errs () << " PERF-ERROR: Return code " << RetCode << " \n " ;
217
+ errs () << ErrBuf;
218
+ deleteTempFile (ErrPath.data ());
219
+ deleteTempFile (OutputPath.data ());
220
+ return NoneType ();
221
+ }
222
+
223
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
224
+ MemoryBuffer::getFileOrSTDIN (OutputPath.data ());
225
+ if (std::error_code EC = MB.getError ()) {
226
+ errs () << " Cannot open " << PerfTasksOutputPath.data () << " : "
227
+ << EC.message () << " \n " ;
228
+ deleteTempFile (ErrPath.data ());
229
+ deleteTempFile (OutputPath.data ());
230
+ return NoneType ();
231
+ }
232
+
233
+ FileBuf.reset (MB->release ());
234
+ ParsingBuf = FileBuf->getBuffer ();
235
+ Col = 0 ;
236
+ Line = 1 ;
237
+ auto ParseResult = parsePerfBuildID ();
238
+ if (!ParseResult) {
239
+ outs () << " PERF2BOLT: Failed to parse build-id from perf output\n " ;
240
+ deleteTempFile (ErrPath.data ());
241
+ deleteTempFile (OutputPath.data ());
242
+ return NoneType ();
243
+ }
244
+
245
+ outs () << " PERF2BOLT: Perf.data build-id is: " << *ParseResult << " \n " ;
246
+
247
+ deleteTempFile (ErrPath.data ());
248
+ deleteTempFile (OutputPath.data ());
249
+ return std::string (ParseResult->data (), ParseResult->size ());
250
+ }
251
+
159
252
bool DataAggregator::checkPerfDataMagic (StringRef FileName) {
160
253
int FD;
161
254
if (sys::fs::openFileForRead (FileName, FD)) {
@@ -175,26 +268,18 @@ bool DataAggregator::checkPerfDataMagic(StringRef FileName) {
175
268
return false ;
176
269
}
177
270
178
- void DataAggregator::deleteTempFiles ( ) {
179
- if (auto Errc = sys::fs::remove (PerfEventsErrPath .data ())) {
271
+ void DataAggregator::deleteTempFile (StringRef File ) {
272
+ if (auto Errc = sys::fs::remove (File .data ())) {
180
273
outs () << " PERF2BOLT: Failed to delete temporary file "
181
- << PerfEventsErrPath << " with error " << Errc.message () << " \n " ;
182
- }
183
-
184
- if (auto Errc = sys::fs::remove (PerfEventsOutputPath.data ())) {
185
- outs () << " PERF2BOLT: Failed to delete temporary file "
186
- << PerfEventsOutputPath << " with error " << Errc.message () << " \n " ;
187
- }
188
-
189
- if (auto Errc = sys::fs::remove (PerfTasksErrPath.data ())) {
190
- outs () << " PERF2BOLT: Failed to delete temporary file "
191
- << PerfTasksErrPath << " with error " << Errc.message () << " \n " ;
274
+ << File << " with error " << Errc.message () << " \n " ;
192
275
}
276
+ }
193
277
194
- if (auto Errc = sys::fs::remove (PerfTasksOutputPath.data ())) {
195
- outs () << " PERF2BOLT: Failed to delete temporary file "
196
- << PerfTasksOutputPath << " with error " << Errc.message () << " \n " ;
197
- }
278
+ void DataAggregator::deleteTempFiles () {
279
+ deleteTempFile (PerfEventsErrPath.data ());
280
+ deleteTempFile (PerfEventsOutputPath.data ());
281
+ deleteTempFile (PerfTasksErrPath.data ());
282
+ deleteTempFile (PerfTasksOutputPath.data ());
198
283
}
199
284
200
285
bool DataAggregator::aggregate (BinaryContext &BC,
@@ -541,7 +626,8 @@ std::error_code DataAggregator::parseEvents() {
541
626
}
542
627
}
543
628
outs () << format (" %.1f%%" , Perc);
544
- outs ().resetColor ();
629
+ if (outs ().has_colors ())
630
+ outs ().resetColor ();
545
631
outs () << " )" ;
546
632
}
547
633
outs () << " \n " ;
@@ -623,6 +709,36 @@ std::error_code DataAggregator::parseTasks() {
623
709
return std::error_code ();
624
710
}
625
711
712
+ Optional<std::pair<StringRef, StringRef>>
713
+ DataAggregator::parseNameBuildIDPair () {
714
+ while (checkAndConsumeFS ()) {}
715
+
716
+ auto BuildIDStr = parseString (FieldSeparator, true );
717
+ if (std::error_code EC = BuildIDStr.getError ())
718
+ return NoneType ();
719
+
720
+ auto NameStr = parseString (FieldSeparator, true );
721
+ if (std::error_code EC = NameStr.getError ())
722
+ return NoneType ();
723
+
724
+ consumeRestOfLine ();
725
+ return std::make_pair (NameStr.get (), BuildIDStr.get ());
726
+ }
727
+
728
+ Optional<StringRef> DataAggregator::parsePerfBuildID () {
729
+ while (hasData ()) {
730
+ auto IDPair = parseNameBuildIDPair ();
731
+ if (!IDPair)
732
+ return NoneType ();
733
+
734
+ if (sys::path::filename (IDPair->first ) != BinaryName)
735
+ continue ;
736
+
737
+ return IDPair->second ;
738
+ }
739
+ return NoneType ();
740
+ }
741
+
626
742
std::error_code DataAggregator::writeAggregatedFile () const {
627
743
std::error_code EC;
628
744
raw_fd_ostream OutFile (OutputFDataName, EC, sys::fs::OpenFlags::F_None);
0 commit comments