This is the mail archive of the
java-discuss@sources.redhat.com
mailing list for the Java project.
RE: Initial profiling results (was: Re: -O2 loop problems)
- To: "'jeff dot sturm at commerceone dot com'" <jeff dot sturm at commerceone dot com>, "tromey at redhat dot com" <tromey at redhat dot com>
- Subject: RE: Initial profiling results (was: Re: -O2 loop problems)
- From: Anthony Green <green at redhat dot com>
- Date: Thu, 4 Jan 2001 16:47:07 -0800
- Cc: "'java-discuss at sources dot redhat dot com'" <java-discuss at sources dot redhat dot com>
- Organization: Red Hat, Inc.
- Reply-To: "green at cygnus dot com" <green at cygnus dot com>
On Thursday, January 04, 2001 3:26 PM, Jeff Sturm [SMTP:jeff.sturm@appnet.com]
wrote:
> I'd love to know how to get at similar hardware event counters on x86. I'm
> not
> familiar with any free tools for that arch.
Here are two ideas. On Red Hat Linux 7 you can use a new set of functions in
glibc which are part of POSIX. They provide a clean interface to a possibly
existing CPU counter. The results are reported in nsecs. Get a RH7 system
(with the i686 version of glibc), look in <time.h> for clock_getcpuclockid()
and timer_gettime(), timer_*().
Then there's this old hack. Compile the following to measure.so and run your
program like so...
$ LD_PRELOAD=measure.so MONITORPROF_OUTPUT=output.txt MyProgram
Then read output.txt. This one measures _Jv_MonitorEnter. (Thanks to Ulrich
Drepper - my source of all things glibc-ish)
#define _GNU_SOURCE
#include <ctype.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int fd = -1;
static int (*monitorenter) (void *obj);
static void
constr (void)
{
const char *fname;
if (fd != -1)
return;
fname = getenv ("MONITORPROF_OUTPUT");
if (fname != NULL && *fname != '\0')
{
int procfd;
fd = creat (fname, 0666);
/* Get the processor frequency. */
procfd = open ("/proc/cpuinfo", O_RDONLY);
if (procfd != -1)
{
char buf[2000];
ssize_t n;
if ((n = read (procfd, buf, sizeof (buf))) > 0)
{
char *cpuhz;
buf[sizeof (buf) - 1] = '\0';
cpuhz = strstr (buf, "cpu MHz");
if (cpuhz != NULL)
{
struct iovec iov[2];
cpuhz += 7;
iov[0].iov_base = (void *) "Processor clock: ";
iov[0].iov_len = strlen (iov[0].iov_base);
while (! isdigit (*cpuhz))
++cpuhz;
iov[1].iov_base = cpuhz;
while (*cpuhz != '\0' && *cpuhz != '\n')
++cpuhz;
*cpuhz++ = '\n';
iov[1].iov_len = cpuhz - (char *) iov[1].iov_base;
writev (fd, iov, 2);
}
}
close (procfd);
}
}
monitorenter = dlsym (RTLD_NEXT, "_Jv_MonitorEnter");
if (monitorenter == NULL)
abort ();
}
int
_Jv_MonitorEnter (void *o)
{
char buf[300];
int length;
unsigned long long int before;
unsigned long long int after;
int result;
asm volatile ("rdtsc" : "=A" (before));
if (! monitorenter)
if (fd == -1)
constr ();
result = monitorenter (o);
asm volatile ("rdtsc" : "=A" (after));
if (fd != -1)
{
length = sprintf (buf, "%20llu\n",
(unsigned long long int) after - before);
write (fd, buf, length);
}
return result;
}
/*
* Local variables:
* compile-command: "gcc -shared -O2 -Wall -fPIC -o measure.so measure.c -ldl"
* End:
*/