gprofng: specify the heap data collection range

Extend the -H option:
 -H {off|on|N1[-N2]}  disable , or enable heap tracing, or
                      specify the heap data collection range.
                      The default is "-H off".

gprofng/ChangeLog
2024-08-08  Vladimir Mezentsev  <vladimir.mezentsev@oracle.com>

	* libcollector/heaptrace.c: Read the range in the -H option.
	Do not collect data if the allocated memory is out of range.
	* src/collctrl.h (heaptrace_mode): Define as char * value.
	* src/envsets.cc: Updated since heaptrace_mode is changed.
	* src/collctrl.cc: Accept the extended -H option.
	* src/gp-collect-app.cc: Accept the extended -H option.
	Remove unused code.
This commit is contained in:
Vladimir Mezentsev 2024-08-08 21:30:08 -07:00
parent c412d3f5d9
commit 6a60060d3e
5 changed files with 90 additions and 137 deletions

View File

@ -61,6 +61,8 @@ static ModuleInterface module_interface = {
static CollectorInterface *collector_interface = NULL;
static int heap_mode = 0;
static size_t start_range = 0;
static size_t end_range = SIZE_MAX;
static CollectorModule heap_hndl = COLLECTOR_MODULE_ERR;
static const Heap_packet heap_packet0 = { .comm.tsize = sizeof ( Heap_packet) };
static __thread int reentrance = 0;
@ -132,6 +134,15 @@ open_experiment (const char *exp)
if (params == NULL) /* Heap data collection not specified */
return COL_ERROR_HEAPINIT;
if (*params != 'o') // Not -H on. Read a range.
{
char *s;
start_range = (size_t) CALL_UTIL (strtoull) (params, &s, 0);
if (*s == '-')
end_range = (size_t) CALL_UTIL (strtoull) (s + 1, &s, 0);
fprintf(stderr, "Range: %lld - %lld\n", (long long) start_range, (long long) end_range);
}
collector_interface->writeLog ("<profile name=\"%s\">\n", SP_JCMD_HEAPTRACE);
collector_interface->writeLog (" <profdata fname=\"%s\"/>\n",
module_interface.description);
@ -264,6 +275,12 @@ malloc (size_t size)
return ret;
}
PUSH_REENTRANCE;
if (size < start_range || size >= end_range)
{
ret = (void *) CALL_REAL (malloc)(size);
POP_REENTRANCE;
return ret;
}
Heap_packet hpacket = heap_packet0;
hpacket.comm.tstamp = gethrtime ();
ret = (void *) CALL_REAL (malloc)(size);
@ -333,6 +350,12 @@ realloc (void *ptr, size_t size)
return ret;
}
PUSH_REENTRANCE;
if (size < start_range || size >= end_range)
{
ret = (void *) CALL_REAL (realloc)(ptr, size);
POP_REENTRANCE;
return ret;
}
Heap_packet hpacket = heap_packet0;
hpacket.comm.tstamp = gethrtime ();
ret = (void *) CALL_REAL (realloc)(ptr, size);
@ -359,6 +382,12 @@ memalign (size_t align, size_t size)
return ret;
}
PUSH_REENTRANCE;
if (size < start_range || size >= end_range)
{
ret = (void *) CALL_REAL (memalign)(align, size);
POP_REENTRANCE;
return ret;
}
Heap_packet hpacket = heap_packet0;
hpacket.comm.tstamp = gethrtime ();
ret = (void *) CALL_REAL (memalign)(align, size);
@ -386,6 +415,12 @@ valloc (size_t size)
return ret;
}
PUSH_REENTRANCE;
if (size < start_range || size >= end_range)
{
ret = (void *) CALL_REAL (valloc)(size);
POP_REENTRANCE;
return ret;
}
Heap_packet hpacket = heap_packet0;
hpacket.comm.tstamp = gethrtime ();
ret = (void *) CALL_REAL (valloc)(size);
@ -416,6 +451,13 @@ calloc (size_t size, size_t esize)
return ret;
}
PUSH_REENTRANCE;
size_t sz = size * esize;
if (sz < start_range || sz >= end_range)
{
ret = (void *) CALL_REAL (calloc)(size, esize);
POP_REENTRANCE;
return ret;
}
Heap_packet hpacket = heap_packet0;
hpacket.comm.tstamp = gethrtime ();
ret = (void *) CALL_REAL (calloc)(size, esize);

View File

@ -227,8 +227,7 @@ Coll_Ctrl::Coll_Ctrl (int _interactive, bool _defHWC, bool _kernelHWC)
synctrace_enabled = 0;
synctrace_thresh = -1;
synctrace_scope = 0;
heaptrace_enabled = 0;
heaptrace_checkenabled = 0;
heaptrace_mode = NULL;
iotrace_enabled = 0;
count_enabled = 0;
Iflag = 0;
@ -300,8 +299,7 @@ Coll_Ctrl::Coll_Ctrl (Coll_Ctrl * cc)
synctrace_enabled = cc->synctrace_enabled;
synctrace_thresh = cc->synctrace_thresh;
synctrace_scope = cc->synctrace_scope;
heaptrace_enabled = cc->heaptrace_enabled;
heaptrace_checkenabled = cc->heaptrace_checkenabled;
heaptrace_mode = dbe_strdup(cc->heaptrace_mode);
iotrace_enabled = cc->iotrace_enabled;
count_enabled = cc->count_enabled;
Iflag = cc->Iflag;
@ -365,6 +363,7 @@ Coll_Ctrl::~Coll_Ctrl ()
free (hwc_string);
free (project_home);
free (java_path);
free (heaptrace_mode);
hwcprof_enabled_cnt = 0;
}
@ -452,7 +451,7 @@ Coll_Ctrl::check_consistency ()
if (count_enabled != 0
&& ((clkprof_default != 1 && clkprof_enabled != 0)
|| hwcprof_enabled_cnt != 0 || synctrace_enabled != 0
|| heaptrace_enabled != 0 || iotrace_enabled != 0))
|| heaptrace_mode != NULL || iotrace_enabled != 0))
return strdup (GTXT ("Count data cannot be collected along with any other data.\n"));
/* if count data, various other options are not allowed */
@ -478,12 +477,12 @@ Coll_Ctrl::check_expt (char **warn)
if (ret != NULL) /* something is wrong, return the error */
return ret;
/* check for heaptrace and java -- warn that it covers native allocations only */
if (heaptrace_enabled == 1 && java_mode == 1 && java_default == 0)
if (heaptrace_mode != NULL && java_mode == 1 && java_default == 0)
*warn = strdup (GTXT ("Note: Heap profiling will only trace native allocations, not Java allocations.\n"));
/* if no profiling data selected, warn the user */
if (clkprof_enabled == 0 && hwcprof_enabled_cnt == 0 && synctrace_enabled == 0
&& heaptrace_enabled == 0 && iotrace_enabled == 0 && count_enabled == 0)
&& heaptrace_mode == NULL && iotrace_enabled == 0 && count_enabled == 0)
*warn = strdup (GTXT ("Warning: No function level data requested; only statistics will be collected.\n\n"));
build_data_desc ();
@ -564,15 +563,8 @@ Coll_Ctrl::show (int i)
sb.appendf ("\t %u. %s\n", ii + 1,
hwc_hwcentry_specd_string (ctrbuf, sizeof (ctrbuf), &hwctr[ii]));
}
if (heaptrace_enabled != 0)
{
if (heaptrace_checkenabled == 0)
sb.append (GTXT ("\theap tracing enabled, no checking\n"));
else if (heaptrace_checkenabled == 1)
sb.append (GTXT ("\theap tracing enabled, over/underrun checking\n"));
else
sb.append (GTXT ("\theap tracing enabled, over/underrun checking and pattern storing\n"));
}
if (heaptrace_mode != NULL)
sb.append (GTXT ("\theap tracing enabled\n"));
if (iotrace_enabled != 0)
sb.append (GTXT ("\tI/O tracing enabled\n"));
switch (count_enabled)
@ -712,10 +704,10 @@ Coll_Ctrl::get_collect_args ()
}
*p++ = sb.toString ();
}
if (heaptrace_enabled != 0)
if (heaptrace_mode != NULL)
{
*p++ = strdup ("-H");
*p++ = strdup ("on");
*p++ = strdup (heaptrace_mode);
}
if (iotrace_enabled != 0)
{
@ -1048,39 +1040,40 @@ Coll_Ctrl::set_heaptrace (const char *string)
{
if (opened == 1)
return strdup (GTXT ("Experiment is active; command ignored.\n"));
free(heaptrace_mode);
heaptrace_mode = NULL; // Same as "off"
if (string != NULL && strcmp (string, "off") == 0)
return NULL;
if (string == NULL || strlen (string) == 0 || strcmp (string, "on") == 0)
heaptrace_mode = strdup ("on");
else if (isdigit (*string))
{
heaptrace_enabled = 1;
char *ret = check_consistency ();
if (ret != NULL)
char *s;
unsigned long long n = strtoull (string, &s, 0);
if (*s == '-' && isdigit (s[1]))
{
heaptrace_enabled = 0;
return ret;
unsigned long long n1 = strtoull (s + 1, &s, 0);
if (n1 < n)
return dbe_sprintf (
GTXT ("Incorrect range in heap trace parameter '%s'\n"), string);
}
return NULL;
if (*s != 0)
return dbe_sprintf (
GTXT ("Incorrect range in heap trace parameter '%s'\n"), string);
heaptrace_mode = strdup (string);
}
if (strcmp (string, "off") == 0)
else
return dbe_sprintf (GTXT ("Unrecognized heap tracing parameter `%s'\n"),
string);
char *ret = check_consistency ();
if (ret != NULL)
{
heaptrace_enabled = 0;
return NULL;
free (heaptrace_mode);
heaptrace_mode = NULL;
return ret;
}
#if 0
if (strcmp (string, "check") == 0)
{
/* set to check for over/underruns */
heaptrace_checkenabled = 1;
heaptrace_enabled = 1;
return NULL;
}
if (strcmp (string, "clear") == 0)
{
/* set to check for over/underruns, and store patterns */
heaptrace_checkenabled = 2;
heaptrace_enabled = 1;
return NULL;
}
#endif
return dbe_sprintf (GTXT ("Unrecognized heap tracing parameter `%s'\n"), string);
return NULL;
}
char *
@ -1675,8 +1668,8 @@ Coll_Ctrl::build_data_desc ()
sb.appendf ("p:%d;", clkprof_timer);
if (synctrace_enabled == 1)
sb.appendf ("s:%d,%d;", synctrace_thresh, synctrace_scope);
if (heaptrace_enabled == 1)
sb.appendf ("H:%d;", heaptrace_checkenabled);
if (heaptrace_mode != NULL && strcmp (heaptrace_mode, "off") != 0)
sb.appendf ("H:%s;", heaptrace_mode);
if (iotrace_enabled == 1)
sb.append ("i:;");
if (hwcprof_enabled_cnt > 0)
@ -2834,7 +2827,7 @@ Coll_Ctrl::get (char * control)
}
if (!strncmp (control, ipc_str_heaptrace, len))
{
if ((heaptrace_enabled == 0))
if (heaptrace_mode == NULL)
return strdup (ipc_str_off);
return strdup (ipc_str_on);
}
@ -3019,7 +3012,8 @@ Coll_Ctrl::unset (char * control)
}
if (!strncmp (control, ipc_str_heaptrace, len))
{
heaptrace_enabled = 0;
free (heaptrace_mode);
heaptrace_mode = NULL;
return NULL;
}
if (!strncmp (control, ipc_str_iotrace, len))

View File

@ -101,8 +101,7 @@ public:
/* set the parameters for heap tracing */
char *set_heaptrace(const char *);
int get_heaptrace_mode() { return heaptrace_enabled; };
int get_heaptrace_checkmode() { return heaptrace_checkenabled; };
char *get_heaptrace_mode() { return heaptrace_mode; };
/* set the parameters for I/O tracing */
char *set_iotrace(const char *);
@ -342,12 +341,7 @@ private:
/* definitions in data_pckts.h */
int synctrace_scope;
int heaptrace_enabled; /* T if heap tracing */
/* if 0 no checking;
* if 1, check for over- and under-write
* if 2, also set patterns in malloc'd and free'd areas
*/
int heaptrace_checkenabled;
char *heaptrace_mode; /* NULL, or on, or off, or range */
int iotrace_enabled; /* T if I/O tracing */
/* count controls */

View File

@ -107,7 +107,7 @@ collect::putenv_libcollector_ld_preloads ()
// for those data types that get extra libs LD_PRELOAD'd, add them
if (cc->get_synctrace_mode () != 0)
add_ld_preload ("libgp-sync.so");
if (cc->get_heaptrace_mode () != 0)
if (cc->get_heaptrace_mode () != NULL)
add_ld_preload ("libgp-heap.so");
if (cc->get_iotrace_mode () != 0)
add_ld_preload ("libgp-iotrace.so");

View File

@ -1403,7 +1403,7 @@ collect::usage ()
end of this long list.
*/
printf ( GTXT (
"Usage: gprofng collect app [OPTION(S)] TARGET [TARGET_ARGUMENTS]\n")),
"Usage: gprofng collect app [OPTION(S)] TARGET [TARGET_ARGUMENTS]\n"));
/*
-------------------------------------------------------------------------------
@ -1481,7 +1481,8 @@ collect::usage ()
" \"n\" selects native/Pthreads, \"j\" selects Java, and \"nj\" selects both;\n"
" the default is \"-s off\".\n"
"\n"
" -H {off|on} disable (off), or enable (on) heap tracing; the default is \"-H off\".\n"
" -H {off|on|N1[-N2]} disable (off), or enable (on) heap tracing, or\n"
" specify the heap data collection range. The default is \"-H off\".\n"
"\n"
" -i {off|on} disable (off), or enable (on) I/O tracing; the default is \"-i off\".\n"
"\n"
@ -1494,84 +1495,6 @@ collect::usage ()
"See also:\n"
"\n"
"gprofng(1), gp-archive(1), gp-display-html(1), gp-display-src(1), gp-display-text(1)\n"));
/*
char *s = dbe_sprintf (GTXT ("Usage: %s <args> target <target-args>\n"),
whoami);
writeStr (usage_fd, s);
free (s);
writeStr (usage_fd, GTXT (" -p {lo|on|hi|off|<value>}\tspecify clock-profiling\n"));
writeStr (usage_fd, GTXT ("\t`lo' per-thread rate of ~10 samples/second\n"));
writeStr (usage_fd, GTXT ("\t`on' per-thread rate of ~100 samples/second (default)\n"));
writeStr (usage_fd, GTXT ("\t`hi' per-thread rate of ~1000 samples/second\n"));
writeStr (usage_fd, GTXT ("\t`off' disable clock profiling\n"));
writeStr (usage_fd, GTXT ("\t<value> specify profile timer period in millisec.\n"));
s = dbe_sprintf (GTXT ("\t\t\tRange on this system is from %.3f to %.3f millisec.\n\t\t\tResolution is %.3f millisec.\n"),
(double) cc->get_clk_min () / 1000.,
(double) cc->get_clk_max () / 1000.,
(double) cc->get_clk_res () / 1000.);
writeStr (usage_fd, s);
free (s);
writeStr (usage_fd, GTXT (" -h <ctr_def>...[,<ctr_n_def>]\tspecify HW counter profiling\n"));
s = dbe_sprintf (GTXT ("\tto see the supported HW counters on this machine, run \"%s -h\" with no other arguments\n"),
whoami);
writeStr (usage_fd, s);
free (s);
writeStr (usage_fd, GTXT (" -s <threshold>[,<scope>]\tspecify synchronization wait tracing\n"));
writeStr (usage_fd, GTXT ("\t<scope> is \"j\" for tracing Java-APIs, \"n\" for tracing native-APIs, or \"nj\" for tracing both\n"));
writeStr (usage_fd, GTXT (" -H {on|off}\tspecify heap tracing\n"));
writeStr (usage_fd, GTXT (" -i {on|off}\tspecify I/O tracing\n"));
writeStr (usage_fd, GTXT (" -N <lib>\tspecify library to exclude count from instrumentation (requires -c also)\n"));
writeStr (usage_fd, GTXT (" \tmultiple -N arguments can be provided\n"));
writeStr (usage_fd, GTXT (" -j {on|off|path}\tspecify Java profiling\n"));
writeStr (usage_fd, GTXT (" -J <java-args>\tspecify arguments to Java for Java profiling\n"));
writeStr (usage_fd, GTXT (" -t <duration>\tspecify time over which to record data\n"));
writeStr (usage_fd, GTXT (" -n\tdry run -- don't run target or collect performance data\n"));
writeStr (usage_fd, GTXT (" -y <signal>[,r]\tspecify delayed initialization and pause/resume signal\n"));
writeStr (usage_fd, GTXT ("\tWhen set, the target starts in paused mode;\n\t if the optional r is provided, it starts in resumed mode\n"));
writeStr (usage_fd, GTXT (" -F {on|off|=<regex>}\tspecify following descendant processes\n"));
writeStr (usage_fd, GTXT (" -a {on|ldobjects|src|usedldobjects|usedsrc|off}\tspecify archiving of binaries and other files;\n"));
writeStr (usage_fd, GTXT (" -S {on|off|<seconds>}\t Set the interval for periodic sampling of process-wide resource utilization\n"));
writeStr (usage_fd, GTXT (" -l <signal>\tspecify signal that will trigger a sample of process-wide resource utilization\n"));
writeStr (usage_fd, GTXT (" -o <expt>\tspecify experiment name\n"));
writeStr (usage_fd, GTXT (" --verbose\tprint expanded log of processing\n"));
writeStr (usage_fd, GTXT (" -C <label>\tspecify comment label (up to 10 may appear)\n"));
writeStr (usage_fd, GTXT (" -V|--version\tprint version number and exit\n"));
*/
/* don't document this feature */
// writeStr (usage_fd, GTXT(" -Z\tPreload mem.so, and launch target [no experiment]\n") );
/*
writeStr (usage_fd, GTXT ("\n See the gp-collect(1) man page for more information\n"));
*/
#if 0
/* print an extended usage message */
/* find a Java for Java profiling, set Java on to check Java */
find_java ();
cc->set_java_mode (NTXT ("on"));
/* check for variable-clock rate */
unsigned char mode = COL_CPUFREQ_NONE;
get_cpu_frequency (&mode);
if (mode != COL_CPUFREQ_NONE)
writeStr (usage_fd, GTXT ("NOTE: system has variable clock frequency, which may cause variable program run times.\n"));
/* show the experiment that would be run */
writeStr (usage_fd, GTXT ("\n Default experiment:\n"));
char *ccret = cc->setup_experiment ();
if (ccret != NULL)
{
writeStr (usage_fd, ccret);
free (ccret);
exit (1);
}
cc->delete_expt ();
ccret = cc->show (1);
if (ccret != NULL)
{
writeStr (usage_fd, ccret);
free (ccret);
}
#endif
}
void