Hey guys,
I'm working on profiling some compiled Gambit Scheme code. I just wrote a quick article on some of my first attempts:
http://jlongster.com/blog/2010/02/17/profiling-gambit/
My question is: what are some best practices? So far, I've compiled my code with "-track-scheme" and "-debug-location". Neither of those help real profilers, but it should help statprof.
First, I tried using real profilers like Shark and Instruments. It worked out pretty good, but is there anything I can do to tell Gambit to compile my code in an orderly way and to do as little rearranging?
Second, I tried statprof. It's great. I was able to get some decent output in my compiled program. I pumped up the thread heartbeat to 1/1000 instead of 1/100. However, strangely enough, when I tried running it straight on my iPhone, I got only ONE entry, the high-level function which runs everything, and of course it said 100%.
I know statprof uses Gambit's internal function for tracking location. How do they work? If I've compiled in "-debug-location" my compiled code, even on the iPhone, should be able to keep track of itself, shouldn't it?
(For those interested, I wrote a little server library which implements "remote files" so that statprof can connect to my computer from my iPhone and tell it to write all the HTML files.)
Also, are there are declarations that will make a difference? My code is being compiled with "(block)", does that mean a lot of things will be collapsed together?
- James
Afficher les réponses par date
Dunno if it will help in your particular case, but check that you're compiling with debugging information on the C level, i.e. passing -g, possibly -O0, maybe -ggdb or -gdwarf-2 to gcc. (There are various ways to do this, from using the cc-options Gambit compiler option (I think -O0 won't help that way) to modifying makefiles [to editing gsc-cc-o.bat in earlier releases] to putting a gcc wrapper earlier in the PATH..)
Christian.
On Wed, Feb 17, 2010 at 5:37 PM, James Long longster@gmail.com wrote:
Second, I tried statprof. It's great. I was able to get some decent output in my compiled program. I pumped up the thread heartbeat to 1/1000 instead of 1/100. However, strangely enough, when I tried running it straight on my iPhone, I got only ONE entry, the high-level function which runs everything, and of course it said 100%.
If Gambit hasn't got native-thread support then you would see this.
On Thu, Feb 18, 2010 at 11:44 AM, Grant Rettke grettke@acm.org wrote:
On Wed, Feb 17, 2010 at 5:37 PM, James Long longster@gmail.com wrote:
Second, I tried statprof. It's great. I was able to get some decent output in my compiled program. I pumped up the thread heartbeat to 1/1000 instead of 1/100. However, strangely enough, when I tried running it straight on my iPhone, I got only ONE entry, the high-level function which runs everything, and of course it said 100%.
If Gambit hasn't got native-thread support then you would see this.
Oh I misunderstood didn't I? Sorry.
On 2010-02-17, at 6:37 PM, James Long wrote:
Second, I tried statprof. It's great. I was able to get some decent output in my compiled program. I pumped up the thread heartbeat to 1/1000 instead of 1/100. However, strangely enough, when I tried running it straight on my iPhone, I got only ONE entry, the high-level function which runs everything, and of course it said 100%.
My guess is that Mac OS X has a broken implementation of setitimer. I've send bug reports to Apple but never heard from them. Bug report attached below.
Marc
/* * File: "timer.c". * * This program was written by Marc Feeley (feeley@iro.umontreal.ca). * * This program exhibits a problem with the ITIMER_VIRTUAL timer on * Mac OS X. It seems that some of the signals that should be generated * are lost. If the ITIMER_REAL timer is used instead, the signals * are generated in a timely manner. Moreover, when the ITIMER_VIRTUAL * timer is used, it seems that generating events (such as moving the * mouse, pressing the shift key on the keyboard, etc) causes the * signals to be generated for a moment. Below is a trace of the execution. * The program should write one V on stdout every 1/10 of a second. * * $ gcc -DUSE_ITIMER_VIRTUAL timer.c * $ time ./a.out * VVVV^C * * real 0m9.489s * user 0m9.470s * sys 0m0.010s * $ gcc -DUSE_ITIMER_REAL timer.c * $ time ./a.out * RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR^C * * real 0m6.737s * user 0m6.590s * sys 0m0.000s * $ uname -a * Darwin bambi.iro.umontreal.ca 7.8.0 Darwin Kernel Version 7.8.0: Wed Dec 22 14:26:17 PST 2004; root:xnu/xnu-517.11.1.obj~1/RELEASE_PPC Power Macintosh powerpc */
#include <sys/time.h> #include <signal.h> #include <stdio.h> #include <unistd.h>
void heartbeat_interrupt_handler (int sig) { #ifdef USE_ITIMER_REAL write (STDOUT_FILENO, "R", 1); #else write (STDOUT_FILENO, "V", 1); #endif }
int main (int argc, char *argv[]) { struct itimerval tv; int secs = 0; int usecs = 100000;
#ifdef USE_ITIMER_REAL int HEARTBEAT_ITIMER = ITIMER_REAL; int SIG = SIGALRM; #else int HEARTBEAT_ITIMER = ITIMER_VIRTUAL; int SIG = SIGVTALRM; #endif
struct sigaction act; act.sa_handler = heartbeat_interrupt_handler; act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif sigemptyset (&act.sa_mask); sigaction (SIG, &act, 0);
tv.it_interval.tv_sec = secs; tv.it_interval.tv_usec = usecs; tv.it_value.tv_sec = secs; tv.it_value.tv_usec = usecs; setitimer (HEARTBEAT_ITIMER, &tv, 0); getitimer (HEARTBEAT_ITIMER, &tv);
for (;;) { /* keep CPU 100% busy */ }
return 0; }
On Thu, Feb 18, 2010 at 12:52 PM, Marc Feeley feeley@iro.umontreal.ca wrote:
My guess is that Mac OS X has a broken implementation of setitimer. I've send bug reports to Apple but never heard from them. Bug report attached below.
Hrmph. This might be the case. How did you fix it on OSX, or is it fixed? statprof seems to run fine for executables on my OSX (10.6). Do you use real timers? Can I compile it the same with for my iPhone?
Here was my test. Did I do this right? This is all running on the iPhone.
(##thread-heartbeat-interval-set! (exact->inexact 1/1000)) (##interrupt-vector-set! 1 (let ((count 0) (time (real-time))) (lambda () (##thread-heartbeat!) (set! count (+ count 1))
(let ((diff (- (real-time) time))) (if (> diff 1.) (begin (pp (list diff count)) (set! count 0) (set! time (real-time))))))))
Output:
(1.0214531421661377 29) (1.0321640968322754 29) (1.0493919849395752 25) (1.0320019721984863 26) (1.0321731567382812 25) (1.0144340991973877 24) (1.0476930141448975 20) (1.0140950679779053 20)
I was expecting the output to be closer to (1.001 1000).
On Wed, 2010-02-17 at 18:37 -0500, James Long wrote:
Hey guys,
I'm working on profiling some compiled Gambit Scheme code. I just wrote a quick article on some of my first attempts:
Cool.
My question is: what are some best practices? So far, I've compiled my code with "-track-scheme" and "-debug-location".
You can recompile the Gambit runtime with these flags, which may help disambiguate some of those calls, I don't know. I first built gambit in the usual way, so that gsc-comp exists, then I
239 13:31 make realclean 244 13:32 ./configure CC=/pkgs/gcc-4.2.4/bin/gcc --enable-single-host --enable-multitple-versions
then I edited lib/makefile by hand to get
.scm.c: $(rootfromhere)/gsc-comp -:~~bin=$(srcdirpfx)$(rootfromhere)/bin,~~lib=$(srcdirpfx)$(rootfromhere)/lib,~~include=$(srcdirpfx)$(rootfromhere)/include -f -c -check -track-scheme -debug-location $(srcdirpfx)$*.scm
It takes quite a bit longer to compile the library files. And I don't quite how to get this to work with a cross-compile. (Build Gambit natively first to get a native gsc-comp, and then build it again as a cross compiler?)
Brad
On Thu, Feb 18, 2010 at 1:39 PM, Bradley Lucier lucier@math.purdue.edu wrote:
You can recompile the Gambit runtime with these flags, which may help disambiguate some of those calls, I don't know.
Brad, that's a good idea. I haven't needed that level of detail yet; the reports that I was getting from the iPhone didn't give me *anything* except pointing to my "render" function, which runs everything. But it would be good to run statprof with Gambit compiled that way, when I'm looking for more details!
I don't think it would complicate cross-compilation, as long as I make sure the same flags I'm using now are passed through.