[dtrace-discuss] I do not understand. Please advise.
Paul van den Bogaard
Paul.VandenBogaard at Sun.COM
Thu Jul 5 10:02:23 PDT 2007
*What
did some further testing on this subject. Please find here my findings and ideas. Still open ended.
I am now stuck in my way of thinking. Like going around in circles. I like to instrument a process of which I know it will be created but I do not have the pid yet. Looking for a creative idea that could help me get out of this chicken and egg situation?
These tests are all performed on a single code AMD U20 workstation running Solaris 10, Update 3.
*Why
I am trying to optimize a JDBC (pure Java) driver used for SPECjApps benchmarks. The SPEC setup is quite complex. Therefore it would be very convenient if I could make this stop in "proc:::exec" work in order to determine the pid of the java process started and then start a next script that needs this pid. This would enable me to focus on tracing specific classes (likely jdbc related).
I have read about other methods to get a VM started with a pause option. Indeed this works, however the stop() and go method I am trying to get working is simpler in use.
*The DTrace scripts:
#!/usr/sbin/dtrace -Zs
#pragma D option quiet
#pragma D option destructive
int watchpid;
proc:::exec-success
/pid == watchpid/
{
stop();
printf("process \"%s\" %d stopped. Use prun %d to activate\n",
stringof(curpsinfo->pr_fname), pid,pid);
system("./misf.d %d", pid);
}
proc:::exec-success
/execname == "java" && watchpid == 0/
{
watchpid = pid;
}
*Some remarks
A java process re-execs itself so I like to get a hold of the second exec. I think the above script takes care of that 'problem'. Now I have a handle on the process. I stop the correct one.
Then it launches the script misf.d with as a single parameter the pid of that java process.
*Interesting Observations:
1) if misf.d is started with the -p pid option (and misf.d has probes specified as "hotspot$target:::method-entry" than this automagically starts the stopped process: no prun is needed.
2) when using it as in the code snippet above and handled like "hotspot$1:::method-entry" I need to use prun to wake up the Java process.
My adhoc impression: an undocumented feature.
*The misf.d script:
#!/usr/sbin/dtrace -Zs
#pragma D option quiet
self string class;
hotspot$1:::method-entry
{
this->str_ptr = (char*) copyin(arg1, arg2+1);
this->str_ptr[arg2] = '\0';
self->class = (string) this->str_ptr;
printf("%s\n", self->class);
}
Of course the original version is a little bit more complex, however this one shows what is happening.
*What happens
If I remove the -Z option from the first line in misf.d (#!/usr/sbin/dtrace -Zs) I get a DTrace error message telling me it found no matching probes. I think this is due to the fact that all these hotspot probes are part of libjvm.so. A library that is not (completely?) loaded at this point in time. When the misf.d script starts the java process is already stopped, therefore this DTrace script does not find any probes.
And indeed leaving the -Z option in place results in absolutely no output at all. Probes that do not exist can not be activated, so will never fire.
*Extra info on the hotspot provider
According to the docs there is a hotspot<pid>:::init-vm-end. I was hoping I could create a clause on the probe spec like "hotspot*:::init-vm-end" and use stop() in this clause. However the probe I am interested in is that of the JVM that still needs to be started and not of any other already started VM. Therefore my probe does not exist and therefore can not be activated: I cannot catch my init-vm-end, since a non-activated probe will never fire...
*Request for enhancement
Both for the hotspot and the pid provider: let the probe specification in DTrace scripts be like a template. Once a probe that matches the template is created (after the DTrace script is started) it will be placed into instrumented mode.
In my example this means I create an interst for the probe "hotspot*:::vm-init-end". Start my DTrace script. And some time later I start a JVM. Since I expressed my interest automatically a probe for this newly created process is activated so it will fire if this VM --in this example-- finishes its initialisation.
*More tests
I also did a two stage stop. ./t.d to create the first stop. This time t.d did not do the system() after that stop().
Then from a different window a
dtrace -wqn 'pidDDDDD::main:entry { stop(); }'
(replace DDDD with the pid of the java proces I just learned)
Indeed this works but while this second stop is holding the app frozen a
dtrace -qn 'hotspotDDDD:::method-entry { printf("Method called\n"); }'
does indeed reproduce that error: no matching probes.
the above mentioned double stops need ofcourse a prun DDDD each to get any progress ;^)
So even if I have a handle on the main() {} of the VM I still have no access to the hotspot probes.
*The Java program
public class T {
public int a() { return (int)(Math.random() * 1000.0);}
public int b() { return a(); }
public int c() { return b() + a(); }
public int d(int a) { return a + c(); }
static public void main(String[] args) throws Exception {
Thread.sleep(1000* Integer.parseInt(args[0]));
System.out.println((new T()).d(1) );
}
}
is started like
java -XX:+ExtendedDTraceProbes T 1
(you have to use Java SE 6 for this)
*Some remarks
when I replace the parameter with say 30 it sleeps 30 seconds before doing the method calling. This gives me enough time to determine its pid and do a misf.d from another shell. In this case the misf.d script behaves as I expect. This is the reason why I think it could be related to library loading.
--
This message posted from opensolaris.org
More information about the dtrace-discuss
mailing list