From: Philippe E. <ph...@us...> - 2002-03-14 02:55:33
|
Update of /cvsroot/oprofile/oprofile/pp In directory usw-pr-cvs1:/tmp/cvs-serv30674/oprofile/pp Modified Files: op_time.cpp opf_filter.cpp opp_symbol.cpp oprofpp.cpp oprofpp.h oprofpp_util.cpp Log Message: pp - handle -c0,1 and --sort for post-profile tools Index: op_time.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/op_time.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- op_time.cpp 7 Mar 2002 19:18:20 -0000 1.24 +++ op_time.cpp 14 Mar 2002 02:55:29 -0000 1.25 @@ -18,10 +18,12 @@ #include <popt.h> #include <stdlib.h> +#include <stdio.h> #include <string> #include <list> #include <iostream> +#include <iomanip> #include <sstream> #include <fstream> #include <algorithm> @@ -45,16 +47,25 @@ using std::ifstream; using std::multimap; using std::pair; +using std::setw; + +/* TODO: if we have a quick read samples files format we can handle a great + * part of complexity here by using samples_files_t to handle straight + * op_time. Just create an artificial symbol that cover the whole samples + * files with the name of the application this allow to remove image_name + * and sorted_map_t class and all related stuff and to use OutputSymbol to + * make the report + */ /// image_name - class to store name for a samples file struct image_name { - image_name(const string& samplefile_name, u32 count = 0); + image_name(const string& samplefile_name); /// total number of samples for this samples file, this is a place /// holder to avoid separate data struct which associate image_name /// with a sample count. - u32 count; + counter_array_t count; /// complete name of the samples file (without leading dir) string samplefile_name; /// application name which belong this sample file, == name if the @@ -69,9 +80,26 @@ typedef multimap<string, image_name> map_t; typedef pair<map_t::iterator, map_t::iterator> pair_it_t; -typedef multimap<u32, map_t::const_iterator> sorted_map_t; -static int counter = -1; +/// comparator for sorted_map_t +struct sort_by_counter_t { + sort_by_counter_t(size_t index_) : index(index_) {} + + bool operator()(const counter_array_t & lhs, + const counter_array_t & rhs) const { + return lhs[index] < rhs[index]; + } + + size_t index; +}; + + +typedef multimap<counter_array_t, map_t::const_iterator, sort_by_counter_t> + sorted_map_t; + +static const char* counter_str; +static int counter; +static int sort_by_counter; static int showvers; static int reverse_sort; static int show_shared_libs; @@ -84,11 +112,10 @@ static OutSymbFlag output_format_flags; -// FIXME: remove demangle/show-image-name since they can be obtained with -// --output_format ? static struct poptOption options[] = { - { "use-counter", 'c', POPT_ARG_INT, &counter, 0, - "use counter", "counter nr", }, + { "counter", 'c', POPT_ARG_STRING, &counter_str, 0, + "which counter to use", "counter nr,[counter nr]", }, + { "sort", 'C', POPT_ARG_INT, &sort_by_counter, 0, "which counter to use for sampels sort", "counter nr", }, { "show-shared-libs", 'k', POPT_ARG_NONE, &show_shared_libs, 0, "show details for shared libs. Only meaningfull if you have profiled with --separate-samples", NULL, }, { "demangle", 'd', POPT_ARG_NONE, &demangle, 0, "demangle GNU C++ symbol names", NULL, }, @@ -171,11 +198,10 @@ if (file) base_dir = file; - if (counter == -1) - counter = 0; + if (!counter_str) + counter_str = "0"; - if (show_image_name) - output_format_flags = static_cast<OutSymbFlag>(output_format_flags | osf_image_name); + counter = counter_mask(counter_str); if (output_format == 0) { output_format = "vspni"; @@ -193,9 +219,12 @@ exit(EXIT_FAILURE); } - output_format_flags = static_cast<OutSymbFlag>(output_format_flags | fl); + output_format_flags = fl; } + if (show_image_name) + output_format_flags = static_cast<OutSymbFlag>(output_format_flags | osf_image_name); + if (path) { add_to_alternate_filename(path, false); } @@ -204,16 +233,14 @@ add_to_alternate_filename(recursive_path, true); } - poptFreeContext(optcon); } /** * image_name - ctor from a sample file name */ -image_name::image_name(const string& samplefile_name, u32 count_) +image_name::image_name(const string& samplefile_name) : - count(count_), samplefile_name(samplefile_name) { app_name = extract_app_name(samplefile_name, lib_name); @@ -265,34 +292,72 @@ // the lazilly samples creation it is perfectly correct for one // samples file belonging to counter 0 exist and not exist for // counter 1, so we must filter them. - std::ostringstream s; - s << string(base_dir) << "/" << *it << '#' << counter; - if (file_exist(s.str()) == false) - continue; - - image_name image(*it); + int i; + for (i = 0 ; i < OP_MAX_COUNTERS ; ++i) { + if ((counter & (1 << i)) != 0) { + std::ostringstream s; + s << string(base_dir) << "/" << *it + << '#' << i; + if (file_exist(s.str()) == true) { + break; + } + } + } - result.insert(map_t::value_type(image.app_name, image)); + if (i < OP_MAX_COUNTERS) { + image_name image(*it); + map_t::value_type value(image.app_name, image); + result.insert(value); + } } } /** * out_filename - display a filename and it associated ratio of samples */ -static void out_filename(const string& app_name, size_t app_count, - u32 count, double total_count) +static void out_filename(const string& app_name, + const counter_array_t & app_count, + const counter_array_t & count, + double total_count[OP_MAX_COUNTERS]) { - cout << demangle_filename(app_name) << " " << count << " "; + for (size_t i = 0 ; i < OP_MAX_COUNTERS; ++i) { + if ((counter & (1 << i)) != 0) { + // feel to rewrite with cout and its formated output +#if 1 + printf("%-9d ", count[i]); + double ratio = total_count[i] >= 1.0 + ? count[i] / total_count[i] : 0.0; - if (total_count > 1) { - cout << (count / total_count) * 100 << "%"; - } else { - cout << "0%"; - } + if (ratio < 10.00 / 100.0) + printf(" "); + printf("%2.4f", ratio * 100); - if (app_count != size_t(-1) && (app_count!=0)) - cout << " (" << (count / double(app_count)) * 100 << "%)"; + ratio = app_count[i] >= 1.0 + ? count[i] / app_count[i] : 0.0; + if (ratio < 10.00 / 100.0) + printf(" "); + printf("%2.4f", ratio * 100); +#else + cout << count[i] << " "; + + if (total_count[i] > 1) { + double ratio = count[i] / total_count[i]; + cout << ratio * 100 << "%"; + } else { + cout << "0%"; + } + + if (app_count[i] != 0) { + double ratio = count[i] / double(app_count[i]); + cout << " (" << ratio * 100 << "%)"; + } +#endif + cout << " "; + } + } + + cout << demangle_filename(app_name); cout << endl; } @@ -307,7 +372,8 @@ */ template <class Iterator> static void output_image_samples_count(Iterator first, Iterator last, - u32 app_count, double total_count) + const counter_array_t & app_count, + double total_count[OP_MAX_COUNTERS]) { for (Iterator it = first ; it != last ; ++it) { string name = it->second->second.lib_name; @@ -346,7 +412,7 @@ */ static void output_files_count(map_t& files) { - double total_count = 0; + double total_count[OP_MAX_COUNTERS] = { 0.0 }; /* 1st pass: accumulate for each image_name the samples count and * update the total_count of samples */ @@ -358,23 +424,35 @@ // the range [p_it.first, p_it.second[ belongs to application // it.first->first for ( ; p_it.first != p_it.second ; ++p_it.first) { - std::ostringstream s; - s << string(base_dir) << "/" - << p_it.first->second.samplefile_name - << "#" << counter; + for (int i = 0 ; i < OP_MAX_COUNTERS ; ++i) { + std::ostringstream s; + s << string(base_dir) << "/" + << p_it.first->second.samplefile_name + << "#" << i; + if (file_exist(s.str()) == false) + continue; - samples_file_t samples(s.str()); + samples_file_t samples(s.str()); - u32 count = samples.count(0, samples.nr_samples); + u32 count = + samples.count(0, samples.nr_samples); - p_it.first->second.count = count; - total_count += count; + p_it.first->second.count[i] = count; + total_count[i] += count; + } } it = p_it.second; } - if (total_count == 0.0) { + bool empty = true; + for (int i = 0 ; i < OP_MAX_COUNTERS; ++i) { + if (total_count[i] != 0.0) { + empty = false; + } + } + + if (empty) { cerr << "no samples files found\n"; return; // Would exit(EXIT_FAILURE); perhaps } @@ -383,10 +461,11 @@ * associate with an iterator to a image name e.g. insert one * item for each application */ - sorted_map_t sorted_map; + sort_by_counter_t compare(sort_by_counter); + sorted_map_t sorted_map(compare); for (it = files.begin(); it != files.end() ; ) { pair_it_t p_it = files.equal_range(it->first); - u32 count = 0; + counter_array_t count; for ( ; p_it.first != p_it.second ; ++p_it.first) { count += p_it.first->second.count; } @@ -408,13 +487,15 @@ sorted_map_t::reverse_iterator s_it = sorted_map.rbegin(); for ( ; s_it != sorted_map.rend(); ++s_it) { map_t::const_iterator it = s_it->second; + counter_array_t temp; - out_filename(it->first, size_t(-1), s_it->first, + out_filename(it->first, temp, s_it->first, total_count); if (show_shared_libs) { pair_it_t p_it = files.equal_range(it->first); - sorted_map_t temp_map; + sort_by_counter_t compare(sort_by_counter); + sorted_map_t temp_map(compare); build_sorted_map_by_count(temp_map, p_it); @@ -429,12 +510,14 @@ for ( ; s_it != sorted_map.end() ; ++s_it) { map_t::const_iterator it = s_it->second; - out_filename(it->first, size_t(-1), s_it->first, + counter_array_t temp; + out_filename(it->first, temp, s_it->first, total_count); if (show_shared_libs) { pair_it_t p_it = files.equal_range(it->first); - sorted_map_t temp_map; + sort_by_counter_t compare(sort_by_counter); + sorted_map_t temp_map(compare); build_sorted_map_by_count(temp_map, p_it); @@ -540,7 +623,7 @@ // select the symbols vector<const symbol_entry *> symbols; - samples.select_symbols(symbols, counter, 0.0, false); + samples.select_symbols(symbols, sort_by_counter, 0.0, false); OutputSymbol out(samples, counter); @@ -573,7 +656,7 @@ * files rather getting the whole directory. Code in op_merge can * be probably re-used */ list<string> file_list; - get_sample_file_list(file_list, base_dir, "*"); + get_sample_file_list(file_list, base_dir, "*#*"); map_t file_map; sort_file_list_by_name(file_map, file_list); Index: opf_filter.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/opf_filter.cpp,v retrieving revision 1.56 retrieving revision 1.57 diff -u -d -r1.56 -r1.57 --- opf_filter.cpp 4 Mar 2002 00:12:43 -0000 1.56 +++ opf_filter.cpp 14 Mar 2002 02:55:29 -0000 1.57 @@ -954,7 +954,7 @@ get_options(argc, argv, image_name, sample_file, counter); if (counter != -1 && sort_by_counter != -1 && - counter != sort_by_counter) { + counter != (1 << sort_by_counter)) { cerr << "mismatch between --sort-by-counter and samples filename counter suffix.\n"; exit(EXIT_FAILURE); } @@ -980,7 +980,7 @@ no_output_filter ? no_output_filter : "", assembly, source_with_assembly); - if (output.treat_input(image_name, sample_file, counter) == false) + if (output.treat_input(image_name, sample_file, -1) == false) return EXIT_FAILURE; } Index: opp_symbol.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/opp_symbol.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- opp_symbol.cpp 13 Mar 2002 21:26:42 -0000 1.6 +++ opp_symbol.cpp 14 Mar 2002 02:55:29 -0000 1.7 @@ -147,6 +147,8 @@ flags = static_cast<OutSymbFlag>(flags | flag); } +// TODO: (and also in OutputHeader(). Add the blank when outputting +// the next field not the current to avoid filling with blank the eol. void OutputSymbol::OutputField(ostream & out, const string & name, const sample_entry & sample, OutSymbFlag fl, int ctr) @@ -178,8 +180,6 @@ } } -// TODO: (and also in OutputHeader(). Add the blank when outputting -// the next field not the current to avoid filling with blank the eol. void OutputSymbol::Output(ostream & out, const symbol_entry * symb) { DoOutput(out, symb->name, symb->sample, flags); @@ -237,7 +237,7 @@ // now the repeated field. for (int ctr = 0 ; ctr < int(samples_files.get_nr_counters()); ++ctr) { - if (ctr == counter || counter == -1) { + if ((counter & (1 << ctr)) != 0) { size_t repeated_flag = (flag & osf_repeat_mask); for (size_t i = 0 ; repeated_flag != 0 ; ++i) { if ((repeated_flag & (1 << i)) != 0) { @@ -284,7 +284,7 @@ // now the repeated field. for (int ctr = 0 ; ctr < int(samples_files.get_nr_counters()); ++ctr) { - if (ctr == counter || counter == -1) { + if ((counter & (1 << ctr)) != 0) { size_t repeated_flag = (flags & osf_repeat_mask); for (size_t i = 0 ; repeated_flag != 0 ; ++i) { if ((repeated_flag & (1 << i)) != 0) { Index: oprofpp.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/oprofpp.cpp,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- oprofpp.cpp 7 Mar 2002 19:18:21 -0000 1.30 +++ oprofpp.cpp 14 Mar 2002 02:55:29 -0000 1.31 @@ -30,8 +30,9 @@ using std::cout; using std::cerr; -static int ctr = -1; +static char * ctr_str; static int showvers; +static int sort_by_counter; static char *gproffile; static char *symbol; static int list_symbols; @@ -48,7 +49,8 @@ { "dump-gprof-file", 'g', POPT_ARG_STRING, &gproffile, 0, "dump gprof format file", "file", }, { "list-symbol", 's', POPT_ARG_STRING, &symbol, 0, "give detailed samples for a symbol", "symbol", }, { "demangle", 'd', POPT_ARG_NONE, &demangle, 0, "demangle GNU C++ symbol names", NULL, }, - { "counter", 'c', POPT_ARG_INT, &ctr, 0, "which counter to use", "counter number", }, + { "counter", 'c', POPT_ARG_STRING, &ctr_str, 0, "which counter to display", "counter number[,counter nr]", }, + { "sort", 'C', POPT_ARG_INT, &sort_by_counter, 0, "which counter to use for sampels sort", "counter nr", }, { "version", 'v', POPT_ARG_NONE, &showvers, 0, "show version", NULL, }, { "verbose", 'V', POPT_ARG_NONE, &verbose, 0, "verbose output", NULL, }, { "base-dir", 'b', POPT_ARG_STRING, &basedir, 0, "base directory of profile daemon", NULL, }, @@ -128,7 +130,11 @@ output_format_flags = static_cast<OutSymbFlag>(output_format_flags | fl); } - counter = ctr; + if (!ctr_str) + ctr_str = "0"; + + counter = counter_mask(ctr_str); + opp_treat_options(file, optcon, image_file, sample_file, counter); poptFreeContext(optcon); @@ -176,7 +182,7 @@ * Lists all the symbols in decreasing sample count * order, to standard out. */ -void opp_samples_files::do_list_symbols(opp_bfd & abfd) const +void opp_samples_files::do_list_symbols(opp_bfd & abfd, int sort_by_ctr) const { samples_files_t samples; @@ -185,11 +191,12 @@ vector<const symbol_entry *> symbols; - samples.select_symbols(symbols, counter, 0.0, false); + samples.select_symbols(symbols, sort_by_ctr, 0.0, false); OutputSymbol out(samples, counter); out.SetFlag(output_format_flags); + out.SetFlag(osf_show_all_counters); out.Output(cout, symbols, true); } @@ -214,7 +221,7 @@ samples_files_t samples; output_format_flags = - static_cast<OutSymbFlag>(output_format_flags | osf_details); + static_cast<OutSymbFlag>(output_format_flags | osf_details | osf_show_all_counters); samples.add(*this, abfd, true, output_format_flags, false, counter); @@ -252,7 +259,7 @@ * * this use the grpof format <= gcc 3.0 */ -void opp_samples_files::do_dump_gprof(opp_bfd & abfd) const +void opp_samples_files::do_dump_gprof(opp_bfd & abfd, int sort_by_ctr) const { static gmon_hdr hdr = { { 'g', 'm', 'o', 'n' }, GMON_VERSION, {0,0,0,},}; FILE *fp; @@ -310,7 +317,7 @@ pos = (abfd.sym_offset(i, j) + abfd.syms[i]->value + abfd.syms[i]->section->vma - low_pc) / MULTIPLIER; /* opp_get_options have set ctr to one value != -1 */ - count = samples_count(counter, j); + count = samples_count(sort_by_ctr, j); if (pos >= histsize) { fprintf(stderr, "Bogus histogram bin %u, larger than %u !", pos, histsize); @@ -335,13 +342,14 @@ } /** - * do_list_all_symbols_details - list all samples for all symbols. + * do_list_symbols_details - list all samples for all symbols. * @abfd: the bfd object from where come the samples * * Lists all the samples for all the symbols, from the image specified by * @abfd, in increasing order of vma, to standard out. */ -void opp_samples_files::do_list_all_symbols_details(opp_bfd & abfd) const +void opp_samples_files::do_list_symbols_details(opp_bfd & abfd, + int sort_by_ctr) const { samples_files_t samples; @@ -353,9 +361,9 @@ vector<const symbol_entry *> symbols; - samples.select_symbols(symbols, first_file, 0.0, false, true); + samples.select_symbols(symbols, sort_by_ctr, 0.0, false, true); - OutputSymbol out(samples, -1); + OutputSymbol out(samples, counter); out.SetFlag(output_format_flags); @@ -407,7 +415,7 @@ { string image_file; string sample_file; - int counter = -1; + int counter = 0; opp_get_options(argc, argv, image_file, sample_file, counter); opp_samples_files samples_files(sample_file, counter); @@ -417,13 +425,13 @@ samples_files.output_header(); if (list_symbols) - samples_files.do_list_symbols(abfd); + samples_files.do_list_symbols(abfd, sort_by_counter); else if (symbol) samples_files.do_list_symbol(abfd); else if (gproffile) - samples_files.do_dump_gprof(abfd); + samples_files.do_dump_gprof(abfd, sort_by_counter); else if (list_all_symbols_details) - samples_files.do_list_all_symbols_details(abfd); + samples_files.do_list_symbols_details(abfd, sort_by_counter); return 0; } Index: oprofpp.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/oprofpp.h,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- oprofpp.h 3 Mar 2002 01:18:19 -0000 1.41 +++ oprofpp.h 14 Mar 2002 02:55:29 -0000 1.42 @@ -69,6 +69,10 @@ bool is_excluded_symbol(const std::string & symbol); void check_headers(const opd_header * f1, const opd_header * f2); +// given a --counter=0,1,..., option parameter return a mask representing +// each counter. Bit i is oon if counter i was specified. +uint counter_mask(const std::string &); + // defined in oprofpp_util.cpp extern int verbose; extern int demangle; @@ -166,11 +170,10 @@ opp_samples_files(const std::string & sample_file, int counter); ~opp_samples_files(); - void do_list_all_symbols_details(opp_bfd & abfd) const; - void do_list_symbol_details(opp_bfd & abfd, uint sym_idx) const; - void do_dump_gprof(opp_bfd & abfd) const; - void do_list_symbols(opp_bfd & abfd) const; - void do_list_symbol(opp_bfd & abfd) const; + void do_list_symbols_details(opp_bfd & abfd, int sort_by_ctr) const; + void do_dump_gprof(opp_bfd & abfd, int sort_by_ctr) const; + void do_list_symbols(opp_bfd & abfd, int sort_by_ctr) const; + void do_list_symbol(opp_bfd & abfd/*, int sort_by_ctr*/) const; /** * is_open - test if a samples file is open Index: oprofpp_util.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/pp/oprofpp_util.cpp,v retrieving revision 1.36 retrieving revision 1.37 diff -u -d -r1.36 -r1.37 --- oprofpp_util.cpp 13 Mar 2002 21:26:42 -0000 1.36 +++ oprofpp_util.cpp 14 Mar 2002 02:55:29 -0000 1.37 @@ -28,6 +28,7 @@ #include "../util/string_manip.h" using std::string; +using std::vector; int verbose; char const *samplefile; @@ -36,7 +37,7 @@ int demangle; int list_all_symbols_details; const char * exclude_symbols_str; -static std::vector<std::string> exclude_symbols; +static vector<string> exclude_symbols; /** * verbprintf @@ -207,28 +208,25 @@ sscanf(file_ctr_str + 1, "%d", &temp_counter); } - if (counter != temp_counter) { - /* a --counter=x have priority on the # suffixe of filename */ - if (counter != -1 && temp_counter != -1) + if (temp_counter != -1 && counter != -1) { + if ((counter & (1 << temp_counter)) == 0) quit_error(optcon, "oprofpp: conflict between given counter and counter of samples file.\n"); } - if (counter == -1) - counter = temp_counter; - if (counter == -1) { - /* list_all_symbols_details always output all counter */ - if (!list_all_symbols_details) - counter = 0; + if (temp_counter != -1) + counter = 1 << temp_counter; + else + counter = 1 << 0; // use counter 0 } /* chop suffixes */ if (file_ctr_str) file_ctr_str[0] = '\0'; - /* check we have a valid ctr */ - if (counter != -1 && (counter < 0 || counter >= OP_MAX_COUNTERS)) { - fprintf(stderr, "oprofpp: invalid counter number %u\n", counter); + if (counter + 1 >= 1 << OP_MAX_COUNTERS) { + fprintf(stderr, "oprofpp: invalid counter number %u\n", + counter); exit(EXIT_FAILURE); } @@ -281,6 +279,27 @@ } /** + * counter_mask - given a --counter=0,1,..., option parameter return a mask + * representing each counter. Bit i is oon if counter i was specified. + * we allow up to sizeof(uint) * CHAR_BIT different counter + */ +uint counter_mask(const std::string & str) +{ + vector<string> result; + separate_token(result, str, ','); + + uint mask = 0; + for (size_t i = 0 ; i < result.size(); ++i) { + istringstream stream(result[i]); + int counter; + stream >> counter; + mask |= 1 << counter; + } + + return mask; +} + +/** * counter_array_t - construct a counter_array_t * * set count to zero for all counter @@ -821,11 +840,11 @@ } for (i = 0; i < OP_MAX_COUNTERS ; ++i) { - if (counter == -1 || counter == (int)i) { - /* if counter == i, this means than we open only one - * samples file so don't allow opening failure to get - * a more precise error message */ - open_samples_file(i, counter != (int)i); + if ((counter & (1 << i)) != 0) { + /* if only the i th bit is set in counter spec we do + * not allow opening failure to get a more precise + * error message */ + open_samples_file(i, (counter & ~(1 << i)) != 0); } } |