Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 */ | 4 */ |
| 5 | 5 |
| 6 | 6 |
| 7 /* XRay -- a simple profiler for Native Client */ | 7 /* XRay -- a simple profiler for Native Client */ |
| 8 | 8 |
| 9 #include <alloca.h> | 9 #include <alloca.h> |
| 10 #include <assert.h> | 10 #include <assert.h> |
| 11 #include <errno.h> | 11 #include <errno.h> |
| 12 #include <stdarg.h> | 12 #include <stdarg.h> |
| 13 #include <stdint.h> | 13 #include <stdint.h> |
| 14 #include <stdio.h> | 14 #include <stdio.h> |
| 15 #include <stdlib.h> | 15 #include <stdlib.h> |
| 16 #include <string.h> | 16 #include <string.h> |
| 17 #include <unistd.h> | 17 #include <unistd.h> |
| 18 #include "xray/xray_priv.h" | 18 #include "xray/xray_priv.h" |
| 19 | 19 |
| 20 #if defined(XRAY) | 20 #if defined(XRAY) |
| 21 | 21 |
| 22 #define FORCE_INLINE __attribute__((always_inline)) | |
| 23 | |
| 24 #if defined(__amd64__) | |
| 25 FORCE_INLINE uint64_t RDTSC64() { | |
| 26 uint64_t a, d; | |
| 27 __asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d)); | |
| 28 return ((uint64_t)a) | (((uint64_t)d) << 32); | |
| 29 } | |
| 30 #define RDTSC(_x) _x = RDTSC64() | |
| 31 #else | |
| 22 #define RDTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x)); | 32 #define RDTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x)); |
| 23 #define FORCE_INLINE __attribute__((always_inline)) | 33 #endif |
| 34 | |
| 24 | 35 |
| 25 /* Use a TLS variable for cheap thread uid. */ | 36 /* Use a TLS variable for cheap thread uid. */ |
| 26 volatile __thread int g_xray_thread_id; | 37 volatile __thread int g_xray_thread_id; |
| 27 | 38 |
| 28 | 39 |
| 29 struct XRayTraceStackEntry { | 40 struct XRayTraceStackEntry { |
| 30 uint32_t depth_addr; | 41 uint32_t depth_addr; |
| 31 uint64_t tsc; | 42 uint64_t tsc; |
| 32 uint32_t dest; | 43 uint32_t dest; |
| 33 uint32_t annotation_index; | 44 uint32_t annotation_index; |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 int XRayTraceBufferNextEntry(int index) { | 595 int XRayTraceBufferNextEntry(int index) { |
| 585 if (XRayTraceBufferIsAnnotation(index)) | 596 if (XRayTraceBufferIsAnnotation(index)) |
| 586 index = XRayTraceBufferSkipAnnotation(index); | 597 index = XRayTraceBufferSkipAnnotation(index); |
| 587 else | 598 else |
| 588 index = XRayTraceBufferIncrementIndex(index); | 599 index = XRayTraceBufferIncrementIndex(index); |
| 589 return index; | 600 return index; |
| 590 } | 601 } |
| 591 | 602 |
| 592 | 603 |
| 593 /* Dumps the trace report for a given frame. */ | 604 /* Dumps the trace report for a given frame. */ |
| 594 void XRayTraceReport(FILE* f, int frame, char* label, float cutoff) { | 605 void XRayTraceReport(FILE* f, int frame, char* label, |
| 606 float percent_cutoff, int ticks_cutoff) { | |
| 595 int index; | 607 int index; |
| 596 int start; | 608 int start; |
| 597 int end; | 609 int end; |
| 598 float total; | 610 float total; |
| 599 int bad_depth = 0; | 611 int bad_depth = 0; |
| 600 char space[257]; | 612 char space[257]; |
| 601 memset(space, ' ', 256); | 613 memset(space, ' ', 256); |
| 602 space[256] = 0; | 614 space[256] = 0; |
| 603 if (NULL == f) { | 615 if (NULL == f) { |
| 604 f = stdout; | 616 f = stdout; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 619 while (index != end) { | 631 while (index != end) { |
| 620 if (!XRayTraceBufferIsAnnotation(index)) { | 632 if (!XRayTraceBufferIsAnnotation(index)) { |
| 621 const char* symbol_name; | 633 const char* symbol_name; |
| 622 char annotation[1024]; | 634 char annotation[1024]; |
| 623 struct XRayTraceBufferEntry* e = &g_xray.buffer[index]; | 635 struct XRayTraceBufferEntry* e = &g_xray.buffer[index]; |
| 624 uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr); | 636 uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr); |
| 625 uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); | 637 uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr); |
| 626 uint32_t ticks = (e->ticks); | 638 uint32_t ticks = (e->ticks); |
| 627 uint32_t annotation_index = (e->annotation_index); | 639 uint32_t annotation_index = (e->annotation_index); |
| 628 float percent = 100.0f * (float)ticks / total; | 640 float percent = 100.0f * (float)ticks / total; |
| 629 if (percent >= cutoff) { | 641 if (percent >= percent_cutoff && ticks >= ticks_cutoff) { |
| 630 if (depth > 250) bad_depth++; | 642 if (depth > 250) bad_depth++; |
|
bradn
2013/06/27 23:01:24
Might be nice to give this (250) a name and move u
nfullagar1
2013/06/27 23:41:55
This code isn't needed, I'll remove it.
| |
| 631 struct XRaySymbol* symbol; | 643 struct XRaySymbol* symbol; |
| 632 symbol = XRaySymbolTableLookup(g_xray.symbols, addr); | 644 symbol = XRaySymbolTableLookup(g_xray.symbols, addr); |
| 633 symbol_name = XRaySymbolGetName(symbol); | 645 symbol_name = XRaySymbolGetName(symbol); |
| 634 if (0 != annotation_index) { | 646 if (0 != annotation_index) { |
| 635 XRayTraceBufferCopyToString(annotation_index, annotation); | 647 XRayTraceBufferCopyToString(annotation_index, annotation); |
| 636 } else { | 648 } else { |
| 637 strcpy(annotation, ""); | 649 strcpy(annotation, ""); |
| 638 } | 650 } |
| 639 fprintf(f, "0x%08X %10ld %5.1f %s%s %s\n", | 651 fprintf(f, "0x%08X %10ld %5.1f %s%s %s\n", |
| 640 (unsigned int)addr, (int64_t)ticks, percent, | 652 (unsigned int)addr, (int64_t)ticks, percent, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 717 index, | 729 index, |
| 718 (int64_t)total_ticks, | 730 (int64_t)total_ticks, |
| 719 capture_size, | 731 capture_size, |
| 720 annotation_count, | 732 annotation_count, |
| 721 label); | 733 label); |
| 722 } | 734 } |
| 723 } | 735 } |
| 724 | 736 |
| 725 | 737 |
| 726 /* Dump a frame report followed by trace report(s) for each frame. */ | 738 /* Dump a frame report followed by trace report(s) for each frame. */ |
| 727 void XRayReport(FILE* f, float cutoff) { | 739 void XRayReport(FILE* f, float percent_cutoff, int ticks_cutoff) { |
| 728 int head; | 740 int head; |
| 729 int index; | 741 int index; |
| 730 int counter = 0; | 742 int counter = 0; |
| 731 fprintf(f, "Number of symbols: %d\n", XRaySymbolCount(g_xray.symbols)); | 743 if (g_xray.symbols) |
| 744 fprintf(f, "Number of symbols: %d\n", XRaySymbolCount(g_xray.symbols)); | |
| 732 XRayFrameReport(f); | 745 XRayFrameReport(f); |
| 733 fprintf(f, "\n"); | 746 fprintf(f, "\n"); |
| 734 head = g_xray.frame.head; | 747 head = g_xray.frame.head; |
| 735 index = g_xray.frame.tail; | 748 index = g_xray.frame.tail; |
| 736 while (index != head) { | 749 while (index != head) { |
| 737 char label[XRAY_MAX_LABEL]; | 750 char label[XRAY_MAX_LABEL]; |
| 738 fprintf(f, "\n"); | 751 fprintf(f, "\n"); |
| 739 XRayFrameMakeLabel(counter, label); | 752 XRayFrameMakeLabel(counter, label); |
| 740 XRayTraceReport(f, index, label, cutoff); | 753 XRayTraceReport(f, index, label, percent_cutoff, ticks_cutoff); |
| 741 index = XRayFrameNext(index); | 754 index = XRayFrameNext(index); |
| 755 | |
| 742 ++counter; | 756 ++counter; |
| 743 } | 757 } |
| 744 fprintf(f, | 758 fprintf(f, |
| 745 "======================================================================\n"); | 759 "======================================================================\n"); |
| 746 #if defined(XRAY_OUTPUT_HASH_COLLISIONS) | 760 #if defined(XRAY_OUTPUT_HASH_COLLISIONS) |
| 747 XRayHashTableHisto(f); | 761 XRayHashTableHisto(f); |
| 748 #endif | 762 #endif |
| 749 } | 763 } |
| 750 | 764 |
| 751 | 765 |
| 752 /* Write a profile report to text file. */ | 766 /* Write a profile report to text file. */ |
| 753 void XRaySaveReport(const char* filename, float cutoff) { | 767 void XRaySaveReport(const char* filename, |
| 768 float percent_cutoff, | |
| 769 int ticks_cutoff) { | |
| 754 FILE* f; | 770 FILE* f; |
| 755 f = fopen(filename, "wt"); | 771 f = fopen(filename, "wt"); |
| 756 if (NULL != f) { | 772 if (NULL != f) { |
| 757 XRayReport(f, cutoff); | 773 XRayReport(f, percent_cutoff, ticks_cutoff); |
| 758 fclose(f); | 774 fclose(f); |
| 759 } | 775 } |
| 760 } | 776 } |
| 761 | 777 |
| 762 | 778 |
| 763 /* Initialize XRay */ | 779 /* Initialize XRay */ |
| 764 void XRayInit(int stack_depth, int buffer_size, int frame_count, | 780 void XRayInit(int stack_depth, int buffer_size, int frame_count, |
| 765 const char* mapfilename) { | 781 const char* mapfilename) { |
| 766 int adj_frame_count = frame_count + 1; | 782 int adj_frame_count = frame_count + 1; |
| 767 assert(false == g_xray.initialized); | 783 assert(false == g_xray.initialized); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 781 g_xray.disabled = 0; | 797 g_xray.disabled = 0; |
| 782 g_xray.annotation_filter = 0xFFFFFFFF; | 798 g_xray.annotation_filter = 0xFFFFFFFF; |
| 783 g_xray.guard0 = XRAY_GUARD_VALUE; | 799 g_xray.guard0 = XRAY_GUARD_VALUE; |
| 784 g_xray.guard1 = XRAY_GUARD_VALUE; | 800 g_xray.guard1 = XRAY_GUARD_VALUE; |
| 785 g_xray.guard2 = XRAY_GUARD_VALUE; | 801 g_xray.guard2 = XRAY_GUARD_VALUE; |
| 786 g_xray.initialized = true; | 802 g_xray.initialized = true; |
| 787 XRaySetMaxStackDepth(stack_depth); | 803 XRaySetMaxStackDepth(stack_depth); |
| 788 XRayReset(); | 804 XRayReset(); |
| 789 | 805 |
| 790 /* Mapfile is optional; we don't need it for captures, only for reports. */ | 806 /* Mapfile is optional; we don't need it for captures, only for reports. */ |
| 791 if (NULL != mapfilename) { | 807 g_xray.symbols = XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); |
| 792 g_xray.symbols = XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); | 808 if (NULL != mapfilename) |
| 793 XRaySymbolTableParseMapfile(g_xray.symbols, mapfilename); | 809 XRaySymbolTableParseMapfile(g_xray.symbols, mapfilename); |
| 794 } | |
| 795 } | 810 } |
| 796 | 811 |
| 797 | 812 |
| 798 /* Shut down and free memory used by XRay. */ | 813 /* Shut down and free memory used by XRay. */ |
| 799 void XRayShutdown() { | 814 void XRayShutdown() { |
| 800 assert(true == g_xray.initialized); | 815 assert(true == g_xray.initialized); |
| 801 assert(NULL == g_xray.recording); | 816 assert(NULL == g_xray.recording); |
| 802 XRayCheckGuards(); | 817 XRayCheckGuards(); |
| 803 if (NULL != g_xray.symbols) { | 818 if (NULL != g_xray.symbols) { |
| 804 XRaySymbolTableFree(g_xray.symbols); | 819 XRaySymbolTableFree(g_xray.symbols); |
| 805 } | 820 } |
| 806 XRayFree(g_xray.frame.entry); | 821 XRayFree(g_xray.frame.entry); |
| 807 XRayFree(g_xray.buffer); | 822 XRayFree(g_xray.buffer); |
| 808 g_xray.initialized = false; | 823 g_xray.initialized = false; |
| 809 } | 824 } |
| 810 | 825 |
| 811 #endif /* XRAY */ | 826 #endif /* XRAY */ |
| 812 | 827 |
| OLD | NEW |