Home | History | Annotate | Download | only in xray
      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