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 |