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