1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. */ 4 5 6 /* XRay -- a simple profiler for Native Client */ 7 8 #include <alloca.h> 9 #include <errno.h> 10 #include <inttypes.h> 11 #include <stdarg.h> 12 #include <stdint.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 #include "xray/xray_priv.h" 18 19 #if defined(XRAY) 20 21 struct XRayTotal { 22 int index; 23 int frame; 24 uint64_t ticks; 25 }; 26 27 28 /* Dumps the trace report for a given frame. */ 29 void XRayTraceReport(struct XRayTraceCapture* capture, 30 FILE* f, 31 int frame, 32 char* label, 33 float percent_cutoff, 34 int ticks_cutoff) { 35 int index; 36 int start; 37 int end; 38 float total; 39 char space[257]; 40 struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture); 41 memset(space, ' ', 256); 42 space[256] = 0; 43 if (NULL == f) { 44 f = stdout; 45 } 46 fprintf(f, 47 "====================================================================\n"); 48 if (NULL != label) 49 fprintf(f, "label %s\n", label); 50 fprintf(f, "\n"); 51 fprintf(f, 52 " Address Ticks Percent Function [annotation...]\n"); 53 fprintf(f, 54 "--------------------------------------------------------------------\n"); 55 total = XRayFrameGetTotalTicks(capture, frame); 56 start = XRayFrameGetTraceStartIndex(capture, frame); 57 end = XRayFrameGetTraceEndIndex(capture, frame); 58 index = start; 59 while (index != end) { 60 if (!XRayTraceIsAnnotation(capture, index)) { 61 const char* symbol_name; 62 char annotation[XRAY_TRACE_ANNOTATION_LENGTH]; 63 struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, index); 64 uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr); 65 uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); 66 uint32_t annotation_index = e->annotation_index; 67 uint64_t ticks = 68 e->end_tick > e->start_tick ? e->end_tick - e->start_tick : 0; 69 float percent = 100.0f * (float)ticks / total; 70 if (percent >= percent_cutoff && ticks >= ticks_cutoff) { 71 struct XRaySymbol* symbol; 72 symbol = XRaySymbolTableLookup(symbols, addr); 73 symbol_name = XRaySymbolGetName(symbol); 74 if (0 != annotation_index) { 75 XRayTraceCopyToString(capture, annotation_index, annotation); 76 } else { 77 strcpy(annotation, ""); 78 } 79 fprintf(f, "0x%08X %12" PRIu64 " %5.1f %s%s %s\n", 80 (unsigned int)addr, ticks, percent, 81 &space[256 - depth], symbol_name, annotation); 82 } 83 } 84 index = XRayTraceNextEntry(capture, index); 85 } 86 fflush(f); 87 } 88 89 90 int qcompare(const void* a, const void* b) { 91 struct XRayTotal* ia = (struct XRayTotal*)a; 92 struct XRayTotal* ib = (struct XRayTotal*)b; 93 if (ib->ticks > ia->ticks) 94 return 1; 95 else if (ib->ticks < ia->ticks) 96 return -1; 97 return 0; 98 } 99 100 101 /* Dumps a frame report */ 102 void XRayFrameReport(struct XRayTraceCapture* capture, FILE* f) { 103 int i; 104 int head = XRayFrameGetHead(capture); 105 int frame = XRayFrameGetTail(capture); 106 int counter = 0; 107 int total_capture = 0; 108 struct XRayTotal* totals; 109 totals = (struct XRayTotal*) 110 alloca(XRayFrameGetCount(capture) * sizeof(struct XRayTotal)); 111 fprintf(f, "\n"); 112 fprintf(f, 113 "Frame# Total Ticks Capture size Annotations Label\n"); 114 fprintf(f, 115 "--------------------------------------------------------------------\n"); 116 while (frame != head) { 117 uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame); 118 int capture_size = XRayFrameGetTraceCount(capture, frame); 119 int annotation_count = XRayFrameGetAnnotationCount(capture, frame); 120 bool valid = XRayFrameIsValid(capture, frame); 121 char label[XRAY_MAX_LABEL]; 122 XRayFrameMakeLabel(capture, counter, label); 123 fprintf(f, " %3d %s %12" PRIu64 " %10d %10d %s\n", 124 counter, 125 valid ? " " : "*", 126 total_ticks, 127 capture_size, 128 annotation_count, 129 label); 130 totals[counter].index = counter; 131 totals[counter].frame = frame; 132 totals[counter].ticks = total_ticks; 133 total_capture += capture_size; 134 ++counter; 135 frame = XRayFrameGetNext(capture, frame); 136 } 137 fprintf(f, 138 "--------------------------------------------------------------------\n"); 139 fprintf(f, 140 "XRay: %d frame(s) %d total capture(s)\n", counter, total_capture); 141 fprintf(f, "\n"); 142 /* Sort and take average of the median cut */ 143 qsort(totals, counter, sizeof(struct XRayTotal), qcompare); 144 fprintf(f, "\n"); 145 fprintf(f, "Sorted by total ticks (most expensive first):\n"); 146 fprintf(f, "\n"); 147 fprintf(f, 148 "Frame# Total Ticks Capture size Annotations Label\n"); 149 fprintf(f, 150 "--------------------------------------------------------------------\n"); 151 for (i = 0; i < counter; ++i) { 152 int index = totals[i].index; 153 int frame = totals[i].frame; 154 uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame); 155 int capture_size = XRayFrameGetTraceCount(capture, frame); 156 int annotation_count = XRayFrameGetAnnotationCount(capture, frame); 157 char label[XRAY_MAX_LABEL]; 158 XRayFrameMakeLabel(capture, index, label); 159 fprintf(f, " %3d %12" PRIu64 " %10d %10d %s\n", 160 index, 161 total_ticks, 162 capture_size, 163 annotation_count, 164 label); 165 } 166 fflush(f); 167 } 168 169 170 /* Dump a frame report followed by trace report(s) for each frame. */ 171 void XRayReport(struct XRayTraceCapture* capture, 172 FILE* f, 173 float percent_cutoff, 174 int ticks_cutoff) { 175 int head = XRayFrameGetHead(capture); 176 int frame = XRayFrameGetTail(capture); 177 int counter = 0; 178 XRayFrameReport(capture, f); 179 fprintf(f, "\n"); 180 while (frame != head) { 181 char label[XRAY_MAX_LABEL]; 182 fprintf(f, "\n"); 183 XRayFrameMakeLabel(capture, counter, label); 184 XRayTraceReport(capture, f, frame, label, percent_cutoff, ticks_cutoff); 185 ++counter; 186 frame = XRayFrameGetNext(capture, frame); 187 } 188 fprintf(f, 189 "====================================================================\n"); 190 #if defined(XRAY_OUTPUT_HASH_COLLISIONS) 191 XRayHashTableHisto(capture, f); 192 #endif 193 fflush(f); 194 } 195 196 /* Write a profile report to text file. */ 197 void XRaySaveReport(struct XRayTraceCapture* capture, 198 const char* filename, 199 float percent_cutoff, 200 int ticks_cutoff) { 201 FILE* f; 202 f = fopen(filename, "wt"); 203 if (NULL != f) { 204 XRayReport(capture, f, percent_cutoff, ticks_cutoff); 205 fclose(f); 206 } 207 } 208 209 #endif /* XRAY */ 210