1 2 /*--------------------------------------------------------------------*/ 3 /*--- For printing superblock profiles m_sbprofile.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2012-2017 Mozilla Foundation 11 12 This program is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation; either version 2 of the 15 License, or (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, but 18 WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 25 02111-1307, USA. 26 27 The GNU General Public License is contained in the file COPYING. 28 */ 29 30 /* Contributed by Julian Seward <jseward@acm.org> */ 31 32 #include "pub_core_basics.h" 33 #include "pub_core_transtab.h" 34 #include "pub_core_libcbase.h" 35 #include "pub_core_libcprint.h" 36 #include "pub_core_libcassert.h" 37 #include "pub_core_debuginfo.h" 38 #include "pub_core_translate.h" 39 #include "pub_core_options.h" 40 #include "pub_core_sbprofile.h" // self 41 42 /*====================================================================*/ 43 /*=== SB profiling ===*/ 44 /*====================================================================*/ 45 46 static UInt n_profiles = 0; 47 48 static 49 void show_SB_profile ( const SBProfEntry tops[], UInt n_tops, 50 ULong score_total, ULong ecs_done ) 51 { 52 ULong score_cumul, score_cumul_saved, score_here; 53 Int r; /* must be signed */ 54 55 HChar ecs_txt[50]; // large enough 56 if (ecs_done > 0) { 57 VG_(sprintf)(ecs_txt, "%'llu ecs done", ecs_done); 58 } else { 59 VG_(strcpy)(ecs_txt, "for the entire run"); 60 } 61 62 vg_assert(VG_(clo_profyle_sbs)); 63 64 VG_(printf)("\n"); 65 VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---" 66 "<<<---<<<---<<<---<<<---<<<---<<<\n"); 67 VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---" 68 "<<<---<<<---<<<---<<<---<<<---<<<\n"); 69 VG_(printf)("\n"); 70 VG_(printf)("<<< BEGIN SB Profile #%u (%s)\n", 71 ++n_profiles, ecs_txt); 72 VG_(printf)("<<<\n"); 73 VG_(printf)("\n"); 74 75 VG_(printf)("Total score = %'llu\n\n", score_total); 76 77 /* Print an initial per-block summary. */ 78 VG_(printf)("rank ---cumulative--- -----self-----\n"); 79 score_cumul = 0; 80 for (r = 0; r < n_tops; r++) { 81 if (tops[r].addr == 0) 82 continue; 83 if (tops[r].score == 0) 84 continue; 85 86 const HChar *name; 87 VG_(get_fnname_w_offset)(tops[r].addr, &name); 88 89 score_here = tops[r].score; 90 score_cumul += score_here; 91 92 /* Careful: do not divide by zero. score_total == 0 implies 93 score_cumul == 0 and also score_here == 0. */ 94 Double percent_cumul = 95 score_total == 0 ? 100.0 : score_cumul * 100.0 / score_total; 96 Double percent_here = 97 score_total == 0 ? 100.0 : score_here * 100.0 / score_total; 98 99 VG_(printf)("%3d: (%9llu %5.2f%%) %9llu %5.2f%% 0x%lx %s\n", 100 r, 101 score_cumul, percent_cumul, 102 score_here, percent_here, tops[r].addr, name); 103 } 104 score_cumul_saved = score_cumul; 105 106 if (VG_(clo_profyle_flags) > 0) { 107 108 /* Show the details, if requested. */ 109 VG_(printf)("\n"); 110 VG_(printf)("-----------------------------" 111 "------------------------------\n"); 112 VG_(printf)("--- SB Profile (SB details) " 113 " ---\n"); 114 VG_(printf)("-----------------------------" 115 "------------------------------\n"); 116 VG_(printf)("\n"); 117 118 score_cumul = 0; 119 for (r = 0; r < n_tops; r++) { 120 if (tops[r].addr == 0) 121 continue; 122 if (tops[r].score == 0) 123 continue; 124 125 const HChar *name; 126 VG_(get_fnname_w_offset)(tops[r].addr, &name); 127 128 score_here = tops[r].score; 129 score_cumul += score_here; 130 131 /* Careful: do not divide by zero. score_total == 0 implies 132 score_cumul == 0 and also score_here == 0. */ 133 Double percent_cumul = 134 score_total == 0 ? 100.0 : score_cumul * 100.0 / score_total; 135 Double percent_here = 136 score_total == 0 ? 100.0 : score_here * 100.0 / score_total; 137 138 VG_(printf)("\n"); 139 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin SB rank %d " 140 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r); 141 VG_(printf)("%3d: (%9llu %5.2f%%) %9llu %5.2f%% 0x%lx %s\n", 142 r, 143 score_cumul, percent_cumul, 144 score_here, percent_here, tops[r].addr, name ); 145 VG_(printf)("\n"); 146 VG_(discard_translations)(tops[r].addr, 1, "bb profile"); 147 VG_(translate)(0, tops[r].addr, True, VG_(clo_profyle_flags), 0, True); 148 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end SB rank %d " 149 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r); 150 } 151 152 /* Print a final per-block summary, in reverse order, for the 153 convenience of people reading up from the end. */ 154 score_cumul = score_cumul_saved; 155 for (r = n_tops-1; r >= 0; r--) { 156 if (tops[r].addr == 0) 157 continue; 158 if (tops[r].score == 0) 159 continue; 160 161 const HChar *name; 162 VG_(get_fnname_w_offset)(tops[r].addr, &name); 163 164 score_here = tops[r].score; 165 166 /* Careful: do not divide by zero. score_total == 0 implies 167 score_cumul == 0 and also score_here == 0. */ 168 Double percent_cumul = 169 score_total == 0 ? 100.0 : score_cumul * 100.0 / score_total; 170 Double percent_here = 171 score_total == 0 ? 100.0 : score_here * 100.0 / score_total; 172 173 VG_(printf)("%3d: (%9llu %5.2f%%) %9llu %5.2f%% 0x%lx %s\n", 174 r, 175 score_cumul, percent_cumul, 176 score_here, percent_here, tops[r].addr, name ); 177 score_cumul -= score_here; 178 } 179 VG_(printf)("rank ---cumulative--- -----self-----\n"); 180 181 } 182 183 VG_(printf)("\n"); 184 VG_(printf)(">>>\n"); 185 VG_(printf)(">>> END SB Profile #%u (%s)\n", 186 n_profiles, ecs_txt); 187 VG_(printf)(">>>\n"); 188 VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---" 189 ">>>--->>>--->>>--->>>--->>>--->>>\n"); 190 VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---" 191 ">>>--->>>--->>>--->>>--->>>--->>>\n"); 192 VG_(printf)("\n"); 193 } 194 195 196 /* Get and print a profile. Also, zero out the counters so that if we 197 call it again later, the second call will only show new work done 198 since the first call. ecs_done == 0 is taken to mean this is a 199 run-end profile. */ 200 void VG_(get_and_show_SB_profile) ( ULong ecs_done ) 201 { 202 /* The number of blocks to show for a end-of-run profile */ 203 # define N_MAX_END 200 204 /* The number of blocks to show for a mid-run profile. */ 205 # define N_MAX_INTERVAL 20 206 vg_assert(N_MAX_INTERVAL <= N_MAX_END); 207 SBProfEntry tops[N_MAX_END]; 208 Int nToShow = ecs_done == 0 ? N_MAX_END : N_MAX_INTERVAL; 209 ULong score_total = VG_(get_SB_profile)(tops, nToShow); 210 show_SB_profile(tops, nToShow, score_total, ecs_done); 211 # undef N_MAX_END 212 # undef N_MAX_INTERVAL 213 } 214 215 216 /*--------------------------------------------------------------------*/ 217 /*--- end m_sbprofile.c ---*/ 218 /*--------------------------------------------------------------------*/ 219