|
From: <sv...@va...> - 2013-12-15 20:24:54
|
Author: philippe
Date: Sun Dec 15 20:24:43 2013
New Revision: 13760
Log:
Implement gdbsrv "v.info stats" command giving statistics for valgrind core + tools
* addition of VG_(needs_print_stats) in pub_tool_tooliface.h
* use the above in memcheck and helgrind
* output valgrind stats and calls print_stats in server.c
Modified:
trunk/NEWS
trunk/coregrind/m_gdbserver/server.c
trunk/coregrind/m_tooliface.c
trunk/coregrind/pub_core_tooliface.h
trunk/docs/xml/manual-core-adv.xml
trunk/gdbserver_tests/mchelp.stdoutB.exp
trunk/helgrind/hg_main.c
trunk/include/pub_tool_tooliface.h
trunk/memcheck/mc_main.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 15 20:24:43 2013
@@ -11,6 +11,11 @@
* ==================== OTHER CHANGES ====================
+* New and modified GDB server monitor features:
+
+ - A new monitor command "v.info stats" that shows various valgrind core and tool
+ statistics.
+
* ==================== FIXED BUGS ====================
The following bugs have been fixed or resolved. Note that "n-i-bz"
Modified: trunk/coregrind/m_gdbserver/server.c
==============================================================================
--- trunk/coregrind/m_gdbserver/server.c (original)
+++ trunk/coregrind/m_gdbserver/server.c Sun Dec 15 20:24:43 2013
@@ -30,6 +30,7 @@
#include "pub_core_execontext.h"
#include "pub_core_syswrap.h" // VG_(show_open_fds)
#include "pub_core_scheduler.h"
+#include "pub_core_transtab.h"
unsigned long cont_thread;
unsigned long general_thread;
@@ -216,6 +217,7 @@
" (with aspacemgr arg, also shows valgrind segments on log ouput)\n"
" v.info exectxt : show stacktraces and stats of all execontexts\n"
" v.info scheduler : show valgrind thread state and stacktrace\n"
+" v.info stats : show various valgrind and tool stats\n"
" v.set debuglog <level> : set valgrind debug log level to <level>\n"
" v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>\n"
" (default traceflags 0b00100000 : show after instrumentation)\n"
@@ -288,7 +290,7 @@
wcmd = strtok_r (NULL, " ", &ssaveptr);
switch (kwdid = VG_(keyword_id)
("all_errors n_errs_found last_error gdbserver_status memory"
- " scheduler open_fds exectxt",
+ " scheduler stats open_fds exectxt",
wcmd, kwd_report_all)) {
case -2:
case -1:
@@ -311,6 +313,8 @@
VG_(gdbserver_status_output)();
break;
case 4: /* memory */
+ VG_(printf) ("%llu bytes have already been allocated.\n",
+ VG_(am_get_anonsize_total)());
VG_(print_all_arena_stats) ();
if (VG_(clo_profile_heap))
VG_(print_arena_cc_analysis) ();
@@ -332,7 +336,18 @@
VG_(show_sched_status) ();
ret = 1;
break;
- case 6: /* open_fds */
+ case 6: /* stats */
+ VG_(print_translation_stats)();
+ VG_(print_tt_tc_stats)();
+ VG_(print_scheduler_stats)();
+ VG_(print_ExeContext_stats)( False /* with_stacktraces */ );
+ VG_(print_errormgr_stats)();
+ if (VG_(needs).print_stats) {
+ VG_TDICT_CALL(tool_print_stats);
+ }
+ ret = 1;
+ break;
+ case 7: /* open_fds */
if (VG_(clo_track_fds))
VG_(show_open_fds) ("");
else
@@ -341,7 +356,7 @@
" to show open fds\n");
ret = 1;
break;
- case 7: /* exectxt */
+ case 8: /* exectxt */
VG_(print_ExeContext_stats) (True /* with_stacktraces */);
ret = 1;
break;
Modified: trunk/coregrind/m_tooliface.c
==============================================================================
--- trunk/coregrind/m_tooliface.c (original)
+++ trunk/coregrind/m_tooliface.c Sun Dec 15 20:24:43 2013
@@ -92,6 +92,7 @@
.client_requests = False,
.syscall_wrapper = False,
.sanity_checks = False,
+ .print_stats = False,
.var_info = False,
.malloc_replacement = False,
.xml_output = False,
@@ -294,6 +295,14 @@
VG_(tdict).tool_expensive_sanity_check = expen;
}
+void VG_(needs_print_stats) (
+ void (*print_stats)(void)
+)
+{
+ VG_(needs).print_stats = True;
+ VG_(tdict).tool_print_stats = print_stats;
+}
+
void VG_(needs_malloc_replacement)(
void* (*malloc) ( ThreadId, SizeT ),
void* (*__builtin_new) ( ThreadId, SizeT ),
Modified: trunk/coregrind/pub_core_tooliface.h
==============================================================================
--- trunk/coregrind/pub_core_tooliface.h (original)
+++ trunk/coregrind/pub_core_tooliface.h Sun Dec 15 20:24:43 2013
@@ -88,6 +88,7 @@
Bool client_requests;
Bool syscall_wrapper;
Bool sanity_checks;
+ Bool print_stats;
Bool var_info;
Bool malloc_replacement;
Bool xml_output;
@@ -149,6 +150,9 @@
Bool (*tool_cheap_sanity_check)(void);
Bool (*tool_expensive_sanity_check)(void);
+ // VG_(needs).print_stats
+ void (*tool_print_stats)(void);
+
// VG_(needs).malloc_replacement
void* (*tool_malloc) (ThreadId, SizeT);
void* (*tool___builtin_new) (ThreadId, SizeT);
Modified: trunk/docs/xml/manual-core-adv.xml
==============================================================================
--- trunk/docs/xml/manual-core-adv.xml (original)
+++ trunk/docs/xml/manual-core-adv.xml Sun Dec 15 20:24:43 2013
@@ -1436,6 +1436,13 @@
</listitem>
<listitem>
+ <para><varname>v.info stats</varname> shows various valgrind core and
+ tool statistics. With this, Valgrind and tool statistics can
+ be examined while running, even without option <option>--stats=yes</option>.
+ </para>
+ </listitem>
+
+ <listitem>
<para><varname>v.set debuglog <intvalue></varname> sets the
Valgrind debug log level to <intvalue>. This allows to
dynamically change the log level of Valgrind e.g. when a problem
Modified: trunk/gdbserver_tests/mchelp.stdoutB.exp
==============================================================================
--- trunk/gdbserver_tests/mchelp.stdoutB.exp (original)
+++ trunk/gdbserver_tests/mchelp.stdoutB.exp Sun Dec 15 20:24:43 2013
@@ -62,6 +62,7 @@
(with aspacemgr arg, also shows valgrind segments on log ouput)
v.info exectxt : show stacktraces and stats of all execontexts
v.info scheduler : show valgrind thread state and stacktrace
+ v.info stats : show various valgrind and tool stats
v.set debuglog <level> : set valgrind debug log level to <level>
v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>
(default traceflags 0b00100000 : show after instrumentation)
Modified: trunk/helgrind/hg_main.c
==============================================================================
--- trunk/helgrind/hg_main.c (original)
+++ trunk/helgrind/hg_main.c Sun Dec 15 20:24:43 2013
@@ -5133,6 +5133,67 @@
);
}
+static void hg_print_stats (void)
+{
+
+ if (1) {
+ VG_(printf)("\n");
+ HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
+ if (HG_(clo_track_lockorders)) {
+ VG_(printf)("\n");
+ HG_(ppWSUstats)( univ_laog, "univ_laog" );
+ }
+ }
+
+ //zz VG_(printf)("\n");
+ //zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries);
+ //zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s);
+ //zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs);
+ //zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches);
+ //zz VG_(printf)(" hbefore: %'10lu of which slow\n",
+ //zz stats__hbefore_gsearches - stats__hbefore_gsearchFs);
+ //zz VG_(printf)(" hbefore: %'10lu stack high water mark\n",
+ //zz stats__hbefore_stk_hwm);
+ //zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals);
+ //zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes);
+
+ VG_(printf)("\n");
+ VG_(printf)(" locksets: %'8d unique lock sets\n",
+ (Int)HG_(cardinalityWSU)( univ_lsets ));
+ if (HG_(clo_track_lockorders)) {
+ VG_(printf)(" univ_laog: %'8d unique lock sets\n",
+ (Int)HG_(cardinalityWSU)( univ_laog ));
+ }
+
+ //VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n",
+ // stats__ga_LL_adds,
+ // (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) );
+
+ VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n",
+ HG_(stats__LockN_to_P_queries),
+ HG_(stats__LockN_to_P_get_map_size)() );
+
+ VG_(printf)("string table map: %'8llu queries (%llu map size)\n",
+ HG_(stats__string_table_queries),
+ HG_(stats__string_table_get_map_size)() );
+ if (HG_(clo_track_lockorders)) {
+ VG_(printf)(" LAOG: %'8d map size\n",
+ (Int)(laog ? VG_(sizeFM)( laog ) : 0));
+ VG_(printf)(" LAOG exposition: %'8d map size\n",
+ (Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0));
+ }
+
+ VG_(printf)(" locks: %'8lu acquires, "
+ "%'lu releases\n",
+ stats__lockN_acquires,
+ stats__lockN_releases
+ );
+ VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks);
+
+ VG_(printf)("\n");
+ libhb_shutdown(True); // This in fact only print stats.
+}
+
static void hg_fini ( Int exitcode )
{
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
@@ -5154,65 +5215,8 @@
if (HG_(clo_sanity_flags))
all__sanity_check("SK_(fini)");
- if (VG_(clo_stats)) {
-
- if (1) {
- VG_(printf)("\n");
- HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
- if (HG_(clo_track_lockorders)) {
- VG_(printf)("\n");
- HG_(ppWSUstats)( univ_laog, "univ_laog" );
- }
- }
-
- //zz VG_(printf)("\n");
- //zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries);
- //zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s);
- //zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs);
- //zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches);
- //zz VG_(printf)(" hbefore: %'10lu of which slow\n",
- //zz stats__hbefore_gsearches - stats__hbefore_gsearchFs);
- //zz VG_(printf)(" hbefore: %'10lu stack high water mark\n",
- //zz stats__hbefore_stk_hwm);
- //zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals);
- //zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes);
-
- VG_(printf)("\n");
- VG_(printf)(" locksets: %'8d unique lock sets\n",
- (Int)HG_(cardinalityWSU)( univ_lsets ));
- if (HG_(clo_track_lockorders)) {
- VG_(printf)(" univ_laog: %'8d unique lock sets\n",
- (Int)HG_(cardinalityWSU)( univ_laog ));
- }
-
- //VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n",
- // stats__ga_LL_adds,
- // (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) );
-
- VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n",
- HG_(stats__LockN_to_P_queries),
- HG_(stats__LockN_to_P_get_map_size)() );
-
- VG_(printf)("string table map: %'8llu queries (%llu map size)\n",
- HG_(stats__string_table_queries),
- HG_(stats__string_table_get_map_size)() );
- if (HG_(clo_track_lockorders)) {
- VG_(printf)(" LAOG: %'8d map size\n",
- (Int)(laog ? VG_(sizeFM)( laog ) : 0));
- VG_(printf)(" LAOG exposition: %'8d map size\n",
- (Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0));
- }
-
- VG_(printf)(" locks: %'8lu acquires, "
- "%'lu releases\n",
- stats__lockN_acquires,
- stats__lockN_releases
- );
- VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks);
-
- VG_(printf)("\n");
- libhb_shutdown(True);
- }
+ if (VG_(clo_stats))
+ hg_print_stats();
}
/* FIXME: move these somewhere sane */
@@ -5305,6 +5309,8 @@
//VG_(needs_sanity_checks) (hg_cheap_sanity_check,
// hg_expensive_sanity_check);
+ VG_(needs_print_stats) (hg_print_stats);
+
VG_(needs_malloc_replacement) (hg_cli__malloc,
hg_cli____builtin_new,
hg_cli____builtin_vec_new,
Modified: trunk/include/pub_tool_tooliface.h
==============================================================================
--- trunk/include/pub_tool_tooliface.h (original)
+++ trunk/include/pub_tool_tooliface.h Sun Dec 15 20:24:43 2013
@@ -451,6 +451,13 @@
Bool(*expensive_sanity_check)(void)
);
+/* Can the tool produce stats during execution? */
+extern void VG_(needs_print_stats) (
+ // Print out tool status. Note that the stats at end of execution
+ // should be output by the VG_(basic_tool_funcs) "fini" function.
+ void (*print_stats)(void)
+);
+
/* Do we need to see variable type and location information? */
extern void VG_(needs_var_info) ( void );
Modified: trunk/memcheck/mc_main.c
==============================================================================
--- trunk/memcheck/mc_main.c (original)
+++ trunk/memcheck/mc_main.c Sun Dec 15 20:24:43 2013
@@ -6539,6 +6539,98 @@
n_SMs * sizeof(SecMap) / (1024 * 1024UL) );
}
+static void mc_print_stats (void)
+{
+ SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
+
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: sanity checks: %d cheap, %d expensive\n",
+ n_sanity_cheap, n_sanity_expensive );
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: auxmaps: %lld auxmap entries (%lldk, %lldM) in use\n",
+ n_auxmap_L2_nodes,
+ n_auxmap_L2_nodes * 64,
+ n_auxmap_L2_nodes / 16 );
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10\n",
+ n_auxmap_L1_searches, n_auxmap_L1_cmps,
+ (10ULL * n_auxmap_L1_cmps)
+ / (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
+ );
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: auxmaps_L2: %lld searches, %lld nodes\n",
+ n_auxmap_L2_searches, n_auxmap_L2_nodes
+ );
+
+ print_SM_info("n_issued ", n_issued_SMs);
+ print_SM_info("n_deissued ", n_deissued_SMs);
+ print_SM_info("max_noaccess ", max_noaccess_SMs);
+ print_SM_info("max_undefined", max_undefined_SMs);
+ print_SM_info("max_defined ", max_defined_SMs);
+ print_SM_info("max_non_DSM ", max_non_DSM_SMs);
+
+ // Three DSMs, plus the non-DSM ones
+ max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
+ // The 3*sizeof(Word) bytes is the AVL node metadata size.
+ // The VG_ROUNDUP is because the OSet pool allocator will/must align
+ // the elements on pointer size.
+ // Note that the pool allocator has some additional small overhead
+ // which is not counted in the below.
+ // Hardwiring this logic sucks, but I don't see how else to do it.
+ max_secVBit_szB = max_secVBit_nodes *
+ (3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
+ max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
+
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: max sec V bit nodes: %d (%ldk, %ldM)\n",
+ max_secVBit_nodes, max_secVBit_szB / 1024,
+ max_secVBit_szB / (1024 * 1024));
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
+ sec_vbits_new_nodes + sec_vbits_updates,
+ sec_vbits_new_nodes, sec_vbits_updates );
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: max shadow mem size: %ldk, %ldM\n",
+ max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
+
+ if (MC_(clo_mc_level) >= 3) {
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
+ stats_ocacheL1_find,
+ stats_ocacheL1_misses,
+ stats_ocacheL1_lossage );
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL1: %'12lu at 0 %'12lu at 1\n",
+ stats_ocacheL1_find - stats_ocacheL1_misses
+ - stats_ocacheL1_found_at_1
+ - stats_ocacheL1_found_at_N,
+ stats_ocacheL1_found_at_1 );
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
+ stats_ocacheL1_found_at_N,
+ stats_ocacheL1_movefwds );
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL1: %'12lu sizeB %'12u useful\n",
+ (UWord)sizeof(OCache),
+ 4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL2: %'12lu refs %'12lu misses\n",
+ stats__ocacheL2_refs,
+ stats__ocacheL2_misses );
+ VG_(message)(Vg_DebugMsg,
+ " ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
+ stats__ocacheL2_n_nodes_max,
+ stats__ocacheL2_n_nodes );
+ VG_(message)(Vg_DebugMsg,
+ " niacache: %'12lu refs %'12lu misses\n",
+ stats__nia_cache_queries, stats__nia_cache_misses);
+ } else {
+ tl_assert(ocacheL1 == NULL);
+ tl_assert(ocacheL2 == NULL);
+ }
+}
+
+
static void mc_fini ( Int exitcode )
{
MC_(print_malloc_stats)();
@@ -6576,95 +6668,8 @@
done_prof_mem();
- if (VG_(clo_stats)) {
- SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
-
- VG_(message)(Vg_DebugMsg,
- " memcheck: sanity checks: %d cheap, %d expensive\n",
- n_sanity_cheap, n_sanity_expensive );
- VG_(message)(Vg_DebugMsg,
- " memcheck: auxmaps: %lld auxmap entries (%lldk, %lldM) in use\n",
- n_auxmap_L2_nodes,
- n_auxmap_L2_nodes * 64,
- n_auxmap_L2_nodes / 16 );
- VG_(message)(Vg_DebugMsg,
- " memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10\n",
- n_auxmap_L1_searches, n_auxmap_L1_cmps,
- (10ULL * n_auxmap_L1_cmps)
- / (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
- );
- VG_(message)(Vg_DebugMsg,
- " memcheck: auxmaps_L2: %lld searches, %lld nodes\n",
- n_auxmap_L2_searches, n_auxmap_L2_nodes
- );
-
- print_SM_info("n_issued ", n_issued_SMs);
- print_SM_info("n_deissued ", n_deissued_SMs);
- print_SM_info("max_noaccess ", max_noaccess_SMs);
- print_SM_info("max_undefined", max_undefined_SMs);
- print_SM_info("max_defined ", max_defined_SMs);
- print_SM_info("max_non_DSM ", max_non_DSM_SMs);
-
- // Three DSMs, plus the non-DSM ones
- max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
- // The 3*sizeof(Word) bytes is the AVL node metadata size.
- // The VG_ROUNDUP is because the OSet pool allocator will/must align
- // the elements on pointer size.
- // Note that the pool allocator has some additional small overhead
- // which is not counted in the below.
- // Hardwiring this logic sucks, but I don't see how else to do it.
- max_secVBit_szB = max_secVBit_nodes *
- (3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
- max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
-
- VG_(message)(Vg_DebugMsg,
- " memcheck: max sec V bit nodes: %d (%ldk, %ldM)\n",
- max_secVBit_nodes, max_secVBit_szB / 1024,
- max_secVBit_szB / (1024 * 1024));
- VG_(message)(Vg_DebugMsg,
- " memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
- sec_vbits_new_nodes + sec_vbits_updates,
- sec_vbits_new_nodes, sec_vbits_updates );
- VG_(message)(Vg_DebugMsg,
- " memcheck: max shadow mem size: %ldk, %ldM\n",
- max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
-
- if (MC_(clo_mc_level) >= 3) {
- VG_(message)(Vg_DebugMsg,
- " ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
- stats_ocacheL1_find,
- stats_ocacheL1_misses,
- stats_ocacheL1_lossage );
- VG_(message)(Vg_DebugMsg,
- " ocacheL1: %'12lu at 0 %'12lu at 1\n",
- stats_ocacheL1_find - stats_ocacheL1_misses
- - stats_ocacheL1_found_at_1
- - stats_ocacheL1_found_at_N,
- stats_ocacheL1_found_at_1 );
- VG_(message)(Vg_DebugMsg,
- " ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
- stats_ocacheL1_found_at_N,
- stats_ocacheL1_movefwds );
- VG_(message)(Vg_DebugMsg,
- " ocacheL1: %'12lu sizeB %'12u useful\n",
- (UWord)sizeof(OCache),
- 4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
- VG_(message)(Vg_DebugMsg,
- " ocacheL2: %'12lu refs %'12lu misses\n",
- stats__ocacheL2_refs,
- stats__ocacheL2_misses );
- VG_(message)(Vg_DebugMsg,
- " ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
- stats__ocacheL2_n_nodes_max,
- stats__ocacheL2_n_nodes );
- VG_(message)(Vg_DebugMsg,
- " niacache: %'12lu refs %'12lu misses\n",
- stats__nia_cache_queries, stats__nia_cache_misses);
- } else {
- tl_assert(ocacheL1 == NULL);
- tl_assert(ocacheL2 == NULL);
- }
- }
+ if (VG_(clo_stats))
+ mc_print_stats();
if (0) {
VG_(message)(Vg_DebugMsg,
@@ -6726,6 +6731,7 @@
VG_(needs_client_requests) (mc_handle_client_request);
VG_(needs_sanity_checks) (mc_cheap_sanity_check,
mc_expensive_sanity_check);
+ VG_(needs_print_stats) (mc_print_stats);
VG_(needs_malloc_replacement) (MC_(malloc),
MC_(__builtin_new),
MC_(__builtin_vec_new),
|