155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdio.h> 255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <unistd.h> 355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdlib.h> 455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <string.h> 555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <inttypes.h> 655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h" 755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options.h" 855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectconst int kMillion = 1000000; 1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectconst int kMHz = 200 * kMillion; 1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectstruct symbol { 1355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project int count; // number of times a function is executed 1455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t elapsed; // elapsed time for this function 1555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}; 1655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef TraceReader<symbol> TraceReaderType; 1855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options-inl.h" 2055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 2155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectstatic const uint32_t kOffsetThreshold = 0x100000; 2255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 2355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project// This comparison function is called from qsort() to sort 2455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project// symbols into decreasing elapsed time. 2555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint cmp_sym_elapsed(const void *a, const void *b) { 2655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project const symbol_type *syma, *symb; 2755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t elapsed1, elapsed2; 2855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 2955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project syma = static_cast<symbol_type const *>(a); 3055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symb = static_cast<symbol_type const *>(b); 3155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project elapsed1 = syma->elapsed; 3255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project elapsed2 = symb->elapsed; 3355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (elapsed1 < elapsed2) 3455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return 1; 3555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (elapsed1 == elapsed2) 3655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return strcmp(syma->name, symb->name); 3755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return -1; 3855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 3955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 4055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectvoid Usage(const char *program) 4155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{ 4255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program); 4355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project OptionsUsage(); 4455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 4555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 4655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) 4755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{ 4855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ParseOptions(argc, argv); 4955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (argc - optind != 2) { 5055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project Usage(argv[0]); 5155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project exit(1); 5255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 5355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 5455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *trace_filename = argv[optind++]; 5555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *elf_file = argv[optind++]; 5655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project TraceReader<symbol> *trace = new TraceReader<symbol>; 5755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->Open(trace_filename); 5855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->SetDemangle(demangle); 5955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->ReadKernelSymbols(elf_file); 6055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->SetRoot(root); 6155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 6255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type dummy; 6355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project dummy.count = 0; 6455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project dummy.elapsed = 0; 6555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *prev_sym = &dummy; 6655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t prev_bb_time = 0; 6755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project while (1) { 6855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *sym; 6955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project BBEvent event; 7055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project BBEvent first_ignored_event; 7155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bool eof = GetNextValidEvent(trace, &event, &first_ignored_event, &sym); 7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // Assign the elapsed time to the previous function symbol 7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t elapsed = 0; 7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (first_ignored_event.time != 0) 7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project elapsed = first_ignored_event.time - prev_bb_time; 7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project else if (!eof) 7955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project elapsed = event.time - prev_bb_time; 8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project prev_sym->elapsed += elapsed; 8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (eof) 8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project prev_bb_time = event.time; 8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sym->count += 1; 8755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project prev_sym = sym; 8855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#if 0 8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("t%lld bb_num: %d, bb_addr: 0x%x func: %s, addr: 0x%x, count: %d\n", 9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bb_time, bb_num, bb_addr, sym->name, sym->addr, sym->count); 9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#endif 9255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project int nsyms; 9555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *syms = trace->GetSymbols(&nsyms); 9655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 9755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // Sort the symbols into decreasing order of elapsed time 9855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project qsort(syms, nsyms, sizeof(symbol_type), cmp_sym_elapsed); 9955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 10055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // Add up all the cycles 10155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t total = 0; 10255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *sym = syms; 10355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project for (int ii = 0; ii < nsyms; ++ii, ++sym) { 10455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project total += sym->elapsed; 10555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 10655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 10755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project double secs = 1.0 * total / kMHz; 10855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("Total seconds: %.2f, total cycles: %lld, MHz: %d\n\n", 10955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project secs, total, kMHz / kMillion); 11055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 11155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t sum = 0; 11255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("Elapsed secs Elapsed cyc %% %% Function\n"); 11355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sym = syms; 11455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project for (int ii = 0; ii < nsyms; ++ii, ++sym) { 11555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (sym->elapsed == 0) 11655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 11755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sum += sym->elapsed; 11855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project double per = 100.0 * sym->elapsed / total; 11955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project double sum_per = 100.0 * sum / total; 12055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project double secs = 1.0 * sym->elapsed / kMHz; 121d4d5b4f63a5760b2212166f539f906edda0bc4deJack Veenstra const char *ksym = " "; 12255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (sym->region->flags & region_type::kIsKernelRegion) 12355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ksym = "k"; 12455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%12.2f %11lld %6.2f %6.2f %s %s\n", 12555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project secs, sym->elapsed, per, sum_per, ksym, sym->name); 12655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 12755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project delete[] syms; 12855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project delete trace; 12955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 13055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return 0; 13155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 132