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