1 /*
2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "BasicProfileResult.h"
8
9 #if __GNUC__ > 2
10 #include <cxxabi.h>
11 #endif
12 #include <stdio.h>
13
14 #include <algorithm>
15 #include <new>
16 #include <StackOrHeapArray.h>
17
18 #include "Options.h"
19 #include "ProfiledEntity.h"
20
21
22 struct HitSymbol {
23 int64 hits;
24 Symbol* symbol;
25 image_id imageID;
26
operator <HitSymbol27 inline bool operator<(const HitSymbol& other) const
28 {
29 return hits > other.hits;
30 }
31 };
32
33
34 // #pragma mark - BasicImageProfileResult
35
36
BasicImageProfileResult(SharedImage * image,image_id id)37 BasicImageProfileResult::BasicImageProfileResult(SharedImage* image,
38 image_id id)
39 :
40 ImageProfileResult(image, id),
41 fSymbolHits(NULL),
42 fUnknownHits(0)
43 {
44 }
45
46
~BasicImageProfileResult()47 BasicImageProfileResult::~BasicImageProfileResult()
48 {
49 }
50
51
52 status_t
Init()53 BasicImageProfileResult::Init()
54 {
55 int32 symbolCount = fImage->SymbolCount();
56 fSymbolHits = new(std::nothrow) int64[symbolCount];
57 if (fSymbolHits == NULL)
58 return B_NO_MEMORY;
59
60 memset(fSymbolHits, 0, 8 * symbolCount);
61
62 return B_OK;
63 }
64
65
66 bool
AddHit(addr_t address)67 BasicImageProfileResult::AddHit(addr_t address)
68 {
69 int32 symbolIndex = fImage->FindSymbol(address);
70 if (symbolIndex < 0)
71 return false;
72
73 fSymbolHits[symbolIndex]++;
74 fTotalHits++;
75
76 return true;
77 }
78
79
80 void
AddUnknownHit()81 BasicImageProfileResult::AddUnknownHit()
82 {
83 fUnknownHits++;
84 fTotalHits++;
85 }
86
87
88 void
AddSymbolHit(int32 symbolIndex)89 BasicImageProfileResult::AddSymbolHit(int32 symbolIndex)
90 {
91 fSymbolHits[symbolIndex]++;
92 }
93
94
95 void
AddImageHit()96 BasicImageProfileResult::AddImageHit()
97 {
98 fTotalHits++;
99 }
100
101
102 const int64*
SymbolHits() const103 BasicImageProfileResult::SymbolHits() const
104 {
105 return fSymbolHits;
106 }
107
108
109 int64
UnknownHits() const110 BasicImageProfileResult::UnknownHits() const
111 {
112 return fUnknownHits;
113 }
114
115
116 // #pragma mark - BasicProfileResult
117
118
BasicProfileResult()119 BasicProfileResult::BasicProfileResult()
120 :
121 fTotalTicks(0),
122 fUnkownTicks(0),
123 fExpectedTicks(0),
124 fDroppedTicks(0),
125 fTotalSampleCount(0)
126 {
127 }
128
129
130 void
AddExpectedTicks(int32 expected)131 BasicProfileResult::AddExpectedTicks(int32 expected)
132 {
133 fExpectedTicks += expected;
134 }
135
136
137 void
AddDroppedTicks(int32 dropped)138 BasicProfileResult::AddDroppedTicks(int32 dropped)
139 {
140 fDroppedTicks += dropped;
141 }
142
143
144 void
PrintResults(ImageProfileResultContainer * container)145 BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
146 {
147 // get hit images
148 BStackOrHeapArray<BasicImageProfileResult*, 128> images(container->CountImages());
149 int32 imageCount = GetHitImages(container, &*images);
150
151 // count symbols
152 int32 symbolCount = 0;
153 for (int32 k = 0; k < imageCount; k++) {
154 BasicImageProfileResult* image = images[k];
155 if (image->TotalHits() > image->UnknownHits())
156 symbolCount += image->GetImage()->SymbolCount();
157 }
158
159 // find and sort the hit symbols
160 BStackOrHeapArray<HitSymbol, 128> hitSymbols(symbolCount);
161 int32 hitSymbolCount = 0;
162
163 for (int32 k = 0; k < imageCount; k++) {
164 BasicImageProfileResult* image = images[k];
165 if (image->TotalHits() > image->UnknownHits()) {
166 Symbol** symbols = image->GetImage()->Symbols();
167 const int64* symbolHits = image->SymbolHits();
168 int32 imageSymbolCount = image->GetImage()->SymbolCount();
169 for (int32 i = 0; i < imageSymbolCount; i++) {
170 if (symbolHits[i] > 0) {
171 HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++];
172 hitSymbol.hits = symbolHits[i];
173 hitSymbol.symbol = symbols[i];
174 hitSymbol.imageID = image->ID();
175 }
176 }
177 }
178 }
179
180 if (hitSymbolCount > 1)
181 std::sort(&*hitSymbols, hitSymbols + hitSymbolCount);
182
183 int64 totalTicks = fTotalTicks;
184 const int64 missedTicks = fExpectedTicks - fTotalTicks;
185
186 fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
187 "(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
188 fEntity->EntityID());
189 fprintf(gOptions.output, " tick interval: %" B_PRIdBIGTIME " us\n",
190 fInterval);
191 fprintf(gOptions.output,
192 " total ticks: %" B_PRId64 " (%" B_PRId64 " us)\n",
193 totalTicks, totalTicks * fInterval);
194 if (fExpectedTicks != 0) {
195 fprintf(gOptions.output,
196 " expected ticks: %" B_PRId64 " (missed %" B_PRId64 ")\n",
197 fExpectedTicks, missedTicks);
198 }
199 if (totalTicks == 0)
200 totalTicks = 1;
201
202 fprintf(gOptions.output,
203 " unknown ticks: %" B_PRId64 " (%" B_PRId64 " us, %6.2f%%)\n",
204 fUnkownTicks, fUnkownTicks * fInterval,
205 100.0 * fUnkownTicks / totalTicks);
206 fprintf(gOptions.output,
207 " dropped ticks: %" B_PRId64 " (%" B_PRId64 " us, %6.2f%%)\n",
208 fDroppedTicks, fDroppedTicks * fInterval,
209 100.0 * fDroppedTicks / totalTicks);
210 if (gOptions.analyze_full_stack) {
211 fprintf(gOptions.output, " samples/tick: %.1f\n",
212 (double)fTotalSampleCount / totalTicks);
213 }
214
215 if (imageCount > 0) {
216 fprintf(gOptions.output, "\n");
217 fprintf(gOptions.output, " hits unknown image\n");
218 fprintf(gOptions.output, " ---------------------------------------"
219 "---------------------------------------\n");
220 for (int32 k = 0; k < imageCount; k++) {
221 BasicImageProfileResult* image = images[k];
222 fprintf(gOptions.output,
223 " %10" B_PRId64 " %10" B_PRId64 " %7" B_PRId32 " %s\n",
224 image->TotalHits(), image->UnknownHits(),
225 image->ID(), image->GetImage()->Name());
226 }
227 }
228
229 if (hitSymbolCount > 0) {
230 fprintf(gOptions.output, "\n");
231 fprintf(gOptions.output, " hits in us in %% "
232 "image function\n");
233 fprintf(gOptions.output, " ---------------------------------------"
234 "---------------------------------------\n");
235 for (int32 i = 0; i < hitSymbolCount; i++) {
236 const HitSymbol& hitSymbol = hitSymbols[i];
237 const Symbol* symbol = hitSymbol.symbol;
238 #if __GNUC__ > 2
239 int status;
240 const char* symbolName = __cxxabiv1::__cxa_demangle(symbol->Name(),
241 NULL, NULL, &status);
242 if (symbolName == NULL)
243 symbolName = symbol->Name();
244 #else
245 const char* symbolName = symbol->Name();
246 #endif
247 fprintf(gOptions.output,
248 " %10" B_PRId64 " %10" B_PRId64 " %6.2f %6" B_PRId32
249 " %s\n", hitSymbol.hits, hitSymbol.hits * fInterval,
250 100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID,
251 symbolName);
252 #if __GNUC__ > 2
253 if (status == 0)
254 free(const_cast<char*>(symbolName));
255 #endif
256 }
257 } else
258 fprintf(gOptions.output, " no functions were hit\n");
259 }
260
261
262 status_t
GetImageProfileResult(SharedImage * image,image_id id,ImageProfileResult * & _imageResult)263 BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
264 ImageProfileResult*& _imageResult)
265 {
266 BasicImageProfileResult* result
267 = new(std::nothrow) BasicImageProfileResult(image, id);
268 if (result == NULL)
269 return B_NO_MEMORY;
270
271 status_t error = result->Init();
272 if (error != B_OK) {
273 delete result;
274 return error;
275 }
276
277 _imageResult = result;
278 return B_OK;
279 }
280
281
282 // #pragma mark - InclusiveProfileResult
283
284
285 void
AddSamples(ImageProfileResultContainer * container,addr_t * samples,int32 sampleCount)286 InclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
287 addr_t* samples, int32 sampleCount)
288 {
289 // Sort the samples. This way hits of the same symbol are
290 // successive and we can avoid incrementing the hit count of the
291 // same symbol twice. Same for images.
292 std::sort(samples, samples + sampleCount);
293
294 int32 unknownSamples = 0;
295 BasicImageProfileResult* previousImage = NULL;
296 int32 previousSymbol = -1;
297
298 for (int32 i = 0; i < sampleCount; i++) {
299 addr_t address = samples[i];
300 addr_t loadDelta;
301 BasicImageProfileResult* image = static_cast<BasicImageProfileResult*>(
302 container->FindImage(address, loadDelta));
303 int32 symbol = -1;
304 if (image != NULL) {
305 symbol = image->GetImage()->FindSymbol(address - loadDelta);
306 if (image != previousImage || symbol != previousSymbol) {
307 if (symbol < 0)
308 image->AddUnknownHit();
309 else
310 image->AddSymbolHit(symbol);
311 }
312
313 if (image != previousImage)
314 image->AddImageHit();
315 } else
316 unknownSamples++;
317
318 previousImage = image;
319 previousSymbol = symbol;
320 }
321
322 if (unknownSamples == sampleCount)
323 fUnkownTicks++;
324
325 fTotalTicks++;
326 fTotalSampleCount += sampleCount;
327 }
328
329
330 // #pragma mark - ExclusiveProfileResult
331
332
333 void
AddSamples(ImageProfileResultContainer * container,addr_t * samples,int32 sampleCount)334 ExclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
335 addr_t* samples, int32 sampleCount)
336 {
337 BasicImageProfileResult* image = NULL;
338 // the image in which we hit a symbol
339 BasicImageProfileResult* firstImage = NULL;
340 // the first image we hit, != image if no symbol was hit
341
342 for (int32 k = 0; k < sampleCount; k++) {
343 addr_t address = samples[k];
344 addr_t loadDelta;
345 image = static_cast<BasicImageProfileResult*>(
346 container->FindImage(address, loadDelta));
347 if (image != NULL) {
348 if (image->AddHit(address - loadDelta))
349 break;
350 if (firstImage == NULL)
351 firstImage = image;
352 image = NULL;
353 }
354 }
355
356 if (image == NULL) {
357 if (firstImage != NULL)
358 firstImage->AddUnknownHit();
359 else
360 fUnkownTicks++;
361 }
362
363 fTotalTicks++;
364 fTotalSampleCount += sampleCount;
365 }
366