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
21struct XRayTotal {
22  int index;
23  int frame;
24  uint64_t ticks;
25};
26
27
28/* Dumps the trace report for a given frame. */
29void 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
90int 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 */
102void 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. */
171void 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. */
197void 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