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: %lld us\n", fInterval); 179 fprintf(gOptions.output, " total ticks: %lld (%lld us)\n", 180 totalTicks, totalTicks * fInterval); 181 if (totalTicks == 0) 182 totalTicks = 1; 183 fprintf(gOptions.output, " unknown ticks: %lld (%lld us, %6.2f%%)\n", 184 fUnkownTicks, fUnkownTicks * fInterval, 185 100.0 * fUnkownTicks / totalTicks); 186 fprintf(gOptions.output, " dropped ticks: %lld (%lld us, %6.2f%%)\n", 187 fDroppedTicks, fDroppedTicks * fInterval, 188 100.0 * fDroppedTicks / totalTicks); 189 if (gOptions.analyze_full_stack) { 190 fprintf(gOptions.output, " samples/tick: %.1f\n", 191 (double)fTotalSampleCount / totalTicks); 192 } 193 194 if (imageCount > 0) { 195 fprintf(gOptions.output, "\n"); 196 fprintf(gOptions.output, " hits unknown image\n"); 197 fprintf(gOptions.output, " ---------------------------------------" 198 "---------------------------------------\n"); 199 for (int32 k = 0; k < imageCount; k++) { 200 BasicImageProfileResult* image = images[k]; 201 fprintf(gOptions.output, " %10lld %10lld %7ld %s\n", 202 image->TotalHits(), image->UnknownHits(), 203 image->ID(), image->GetImage()->Name()); 204 } 205 } 206 207 if (hitSymbolCount > 0) { 208 fprintf(gOptions.output, "\n"); 209 fprintf(gOptions.output, " hits in us in %% " 210 "image function\n"); 211 fprintf(gOptions.output, " ---------------------------------------" 212 "---------------------------------------\n"); 213 for (int32 i = 0; i < hitSymbolCount; i++) { 214 const HitSymbol& hitSymbol = hitSymbols[i]; 215 const Symbol* symbol = hitSymbol.symbol; 216 #if __GNUC__ > 2 217 int status; 218 const char* symbolName = __cxxabiv1::__cxa_demangle(symbol->Name(), 219 NULL, NULL, &status); 220 if (symbolName == NULL) 221 symbolName = symbol->Name(); 222 #else 223 const char* symbolName = symbol->Name(); 224 #endif 225 fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n", 226 hitSymbol.hits, hitSymbol.hits * fInterval, 227 100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID, 228 symbolName); 229 #if __GNUC__ > 2 230 if (status == 0) 231 free(const_cast<char*>(symbolName)); 232 #endif 233 } 234 } else 235 fprintf(gOptions.output, " no functions were hit\n"); 236 } 237 238 239 status_t 240 BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id, 241 ImageProfileResult*& _imageResult) 242 { 243 BasicImageProfileResult* result 244 = new(std::nothrow) BasicImageProfileResult(image, id); 245 if (result == NULL) 246 return B_NO_MEMORY; 247 248 status_t error = result->Init(); 249 if (error != B_OK) { 250 delete result; 251 return error; 252 } 253 254 _imageResult = result; 255 return B_OK; 256 } 257 258 259 // #pragma mark - InclusiveProfileResult 260 261 262 void 263 InclusiveProfileResult::AddSamples(ImageProfileResultContainer* container, 264 addr_t* samples, int32 sampleCount) 265 { 266 // Sort the samples. This way hits of the same symbol are 267 // successive and we can avoid incrementing the hit count of the 268 // same symbol twice. Same for images. 269 std::sort(samples, samples + sampleCount); 270 271 int32 unknownSamples = 0; 272 BasicImageProfileResult* previousImage = NULL; 273 int32 previousSymbol = -1; 274 275 for (int32 i = 0; i < sampleCount; i++) { 276 addr_t address = samples[i]; 277 addr_t loadDelta; 278 BasicImageProfileResult* image = static_cast<BasicImageProfileResult*>( 279 container->FindImage(address, loadDelta)); 280 int32 symbol = -1; 281 if (image != NULL) { 282 symbol = image->GetImage()->FindSymbol(address - loadDelta); 283 if (symbol < 0) { 284 // TODO: Count unknown image hits? 285 } else if (image != previousImage || symbol != previousSymbol) 286 image->AddSymbolHit(symbol); 287 288 if (image != previousImage) 289 image->AddImageHit(); 290 } else 291 unknownSamples++; 292 293 previousImage = image; 294 previousSymbol = symbol; 295 } 296 297 if (unknownSamples == sampleCount) 298 fUnkownTicks++; 299 300 fTotalTicks++; 301 fTotalSampleCount += sampleCount; 302 } 303 304 305 // #pragma mark - ExclusiveProfileResult 306 307 308 void 309 ExclusiveProfileResult::AddSamples(ImageProfileResultContainer* container, 310 addr_t* samples, int32 sampleCount) 311 { 312 BasicImageProfileResult* image = NULL; 313 // the image in which we hit a symbol 314 BasicImageProfileResult* firstImage = NULL; 315 // the first image we hit, != image if no symbol was hit 316 317 for (int32 k = 0; k < sampleCount; k++) { 318 addr_t address = samples[k]; 319 addr_t loadDelta; 320 image = static_cast<BasicImageProfileResult*>( 321 container->FindImage(address, loadDelta)); 322 if (image != NULL) { 323 if (image->AddHit(address - loadDelta)) 324 break; 325 if (firstImage == NULL) 326 firstImage = image; 327 } 328 } 329 330 if (image == NULL) { 331 if (firstImage != NULL) 332 firstImage->AddUnknownHit(); 333 else 334 fUnkownTicks++; 335 } 336 337 fTotalTicks++; 338 fTotalSampleCount += sampleCount; 339 } 340