Bug 394307 - Add macro to extract current instruction count for peak load monitoring
Summary: Add macro to extract current instruction count for peak load monitoring
Status: REPORTED
Alias: None
Product: valgrind
Classification: Developer tools
Component: callgrind (show other bugs)
Version: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Josef Weidendorfer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-05-16 06:18 UTC by Jonas Josefsson
Modified: 2018-09-03 06:38 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonas Josefsson 2018-05-16 06:18:35 UTC
In order to use callgrind to find load peaks, it is necessary to extract the current instruction count from the running program. Currently callgrind just gives the total instruction count which can give information about a mean load but it cannot be used to find peak loads.

I've made a modification to callgrind that adds a macro that does this:

diff --git a/callgrind/callgrind.h b/callgrind/callgrind.h
index f078cc82b..6d3c40951 100644
--- a/callgrind/callgrind.h
+++ b/callgrind/callgrind.h
@@ -78,7 +78,8 @@ typedef
       VG_USERREQ__TOGGLE_COLLECT,
       VG_USERREQ__DUMP_STATS_AT,
       VG_USERREQ__START_INSTRUMENTATION,
-      VG_USERREQ__STOP_INSTRUMENTATION
+      VG_USERREQ__STOP_INSTRUMENTATION,
+      VG_USERREQ__GET_TOTAL_COSTS
    } Vg_CallgrindClientRequest;
 
 /* Dump current state of cost centers, and zero them afterwards */
@@ -126,4 +127,10 @@ typedef
   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STOP_INSTRUMENTATION,  \
                                   0, 0, 0, 0, 0)
 
+#define CALLGRIND_GET_TOTAL_COSTS(rValue)                        \
+  VALGRIND_DO_CLIENT_REQUEST(rValue, 0, VG_USERREQ__GET_TOTAL_COSTS,  \
+                                  0, 0, 0, 0, 0)
+
 #endif /* __CALLGRIND_H */
diff --git a/callgrind/main.c b/callgrind/main.c
index ab4927296..dd59cc208 100644
--- a/callgrind/main.c
+++ b/callgrind/main.c
@@ -1661,6 +1661,20 @@ Bool CLG_(handle_client_request)(ThreadId tid, UWord *args, UWord *ret)
      }
      break;
 
+  case VG_USERREQ__GET_TOTAL_COSTS:
+     {
+        #define UWORD_MAX (~(UWord)0)
+        ULong Ir_total;
+
+        Ir_total = CLG_(current_state).cost[ fullOffset(EG_IR) ];
+        
+        if (Ir_total > UWORD_MAX) // ULong is 64 bits, UWord might be 32 bit
+          Ir_total = UWORD_MAX;
+
+        *ret = ((UWord) Ir_total);
+     }
+     break;
+
    case VG_USERREQ__ZERO_STATS:
      CLG_(zero_all_cost)(True);
       *ret = 0;                 /* meaningless */
(END)


This can be used to track the peak load of a function in the following way:

// Some kind of main loop
unsigned long MaxInstCount = 0;
while(1) 
{
    unsigned long PostInstCount, PreInstCount;

    CALLGRIND_ZERO_STATS;
    CALLGRIND_START_INSTRUMENTATION;

    CALLGRIND_GET_TOTAL_COSTS(PreInstCount);

    // Execute function to monitor
    Execute_Something();

    CALLGRIND_GET_TOTAL_COSTS(PostInstCount);
    
    PostInstCount -= PreInstCount;

    // Find max and dump callgrind stats.
    if (PostInstCount > MaxInstCount)
    {    
         MaxInstCount = PostInstCount;
         CALLGRIND_DUMP_STATS;
    }

    // Write execution time and some other parameters to InstructionFetchLog.txt.
    fprintf(InstructionFetchLog, "%u,%u\n", PostInstCount, SomeInterestingStateInfo);

    // Stop intrumentation
    CALLGRIND_STOP_INSTRUMENTATION;
}