From: Richard P. <ri...@op...> - 2007-09-28 11:25:02
|
On smaller systems the overhead of the opcontrol scripts is not insignificant so I've implemented some lightweight start and stop commands. The idea is you'd run "opcontrol --start-daemon" to setup oprofile but then "opstart" can start the profile at a more precise moment. "opstop" stops profiling in a similar way with minimal overhead but isn't 100% equivalent to "opcontrol --stop" since it doesn't dump the data. One possible drawback is they're only implemented to work with 2.6 kernels (and print a warning otherwise). Are these commands of general interest? I've attached a patch so people can experiment... Richard --- ChangeLog | 7 +++ configure.in | 3 + doc/Makefile.am | 2 + doc/opstart.1.in | 27 +++++++++++++ doc/opstop.1.in | 28 ++++++++++++++ utils/Makefile.am | 9 ++++ utils/opstart.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 180 insertions(+), 1 deletion(-) Index: oprofile/utils/Makefile.am =================================================================== --- oprofile.orig/utils/Makefile.am 2007-09-28 11:55:01.000000000 +0100 +++ oprofile/utils/Makefile.am 2007-09-28 11:55:47.000000000 +0100 @@ -3,8 +3,15 @@ AM_CFLAGS = @OP_CFLAGS@ LIBS=@POPT_LIBS@ @LIBERTY_LIBS@ -bin_PROGRAMS = ophelp +bin_PROGRAMS = ophelp opstart dist_bin_SCRIPTS = opcontrol ophelp_SOURCES = ophelp.c ophelp_LDADD = ../libop/libop.a ../libutil/libutil.a + +opstart_SOURCES = opstart.c + +install-exec-local: + cd $(DESTDIR)/$(bindir) && \ + rm -f opstop && \ + $(LN_S) opstart opstop Index: oprofile/utils/opstart.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/utils/opstart.c 2007-09-28 11:55:47.000000000 +0100 @@ -0,0 +1,105 @@ +/** + * @file opstart.c + * Start/Stop oprofile + * + * @remark Copyright 2007 Openedhand Ltd. + * @remark Read the file COPYING + * + * @author Richard Purdie + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +int main(const int argc, const char* argv[]) +{ + const char *enable = "/dev/oprofile/enable"; + const char *lockfile; + unsigned long dpid; + struct stat sbuf; + FILE *lfile, *efile; + int sig, enb, err; + + lockfile = getenv("LOCK_FILE"); + if (!lockfile) + lockfile = "/var/lib/oprofile/lock"; + + /* Add SESSION_DIR support? */ + + if (geteuid()) { + printf("Error: This program must be run as root.\n"); + return 1; + } + + if (stat(enable, &sbuf)) { + printf("Error: Could not find /dev/oprofile/enable, the" + " kernel module probably isn't loaded.\n"); + printf("This binary only works with 2.6 kernels and oprofile" + " must have been initialised with 'opcontrol --start-daemon'.\n"); + return 1; + } + + if (stat(lockfile, &sbuf)) { + printf("Error: Could not find lockfile %s.\n", lockfile); + printf("The oprofile daemon must be running (oprofile must" + " have been initialised with 'opcontrol --start-daemon').\n"); + return 1; + } + + lfile = fopen(lockfile, "r"); + if (!lfile) { + printf("Error opening lockfile %s.\n", lockfile); + return 1; + } + + err = fscanf(lfile, "%ud", &dpid); + if (err != 1) { + printf("Error reading pid from lockfile %s.\n", lockfile); + return 1; + } + fclose(lfile); + + efile = fopen(enable, "r"); + if (!efile) { + printf("Error opening %s.\n", enable); + return 1; + } + + if (strstr(argv[0], "opstart")) { + printf("Starting Profiler\n"); + sig = SIGUSR1; + enb = 1; + } else if (strstr(argv[0], "opstop")) { + printf("Stopping Oprofile.\n"); + printf("You need to run 'opcontrol --dump' when the session" + " is finished.\n"); + sig = SIGUSR2; + enb = 0; + } else { + printf("Error: Please call as 'opstart' or 'opstop'\n"); + return 1; + } + + err = kill(dpid, 0); + if (err) { + printf("Error sending signal to oprofiled. Stale lockfile" + " (%s) ?\n", lockfile); + return 1; + } + + fprintf(efile, "%d\n", enb); + err = kill(dpid, sig); + if (err) { + printf("Error sending signal to oprofiled. Stale lockfile" + " (%s) ?\n", lockfile); + return 1; + } + + return 0; +} + Index: oprofile/configure.in =================================================================== --- oprofile.orig/configure.in 2007-09-28 11:55:01.000000000 +0100 +++ oprofile/configure.in 2007-09-28 12:06:28.000000000 +0100 @@ -16,6 +16,7 @@ AM_INIT_AUTOMAKE(oprofile, 0.9.4cvs) AM_CONFIG_HEADER(config.h) AC_PROG_RANLIB +AC_PROG_LN_S dnl for the man page DATE="`date '+%a %d %B %Y'`" @@ -227,6 +228,8 @@ AC_OUTPUT(Makefile \ doc/xsl/catalog-1.xml \ doc/oprofile.1 \ doc/opcontrol.1 \ + doc/opstart.1 \ + doc/opstop.1 \ doc/ophelp.1 \ doc/opreport.1 \ doc/opannotate.1 \ Index: oprofile/ChangeLog =================================================================== --- oprofile.orig/ChangeLog 2007-09-28 11:55:35.000000000 +0100 +++ oprofile/ChangeLog 2007-09-28 11:56:51.000000000 +0100 @@ -1,5 +1,12 @@ 2007-09-28 Richard Purdie <rp...@op...> + * configure.in: + * utils/Makefile.am: + * utils/opstart.c: Add opstart/opstop commands to minimise overhead + in starting/stopping profiling + +2007-09-28 Richard Purdie <rp...@op...> + * events/arm/armv6/events: Fix armv6 events to match mainline kernels 2007-09-25 Brian Twichell <tb...@us...> Index: oprofile/doc/Makefile.am =================================================================== --- oprofile.orig/doc/Makefile.am 2007-09-28 12:05:02.000000000 +0100 +++ oprofile/doc/Makefile.am 2007-09-28 12:05:26.000000000 +0100 @@ -11,6 +11,8 @@ STYLESHEETS=$(CHUNK_XHTML_STYLESHEET) $( man_MANS = \ oprofile.1 \ opcontrol.1 \ + opstart.1 \ + opstop.1 \ opreport.1 \ opannotate.1 \ opgprof.1 \ Index: oprofile/doc/opstart.1.in =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/doc/opstart.1.in 2007-09-28 12:08:14.000000000 +0100 @@ -0,0 +1,27 @@ +.TH OPSTART 1 "@DATE@" "oprofile @VERSION@" +.UC 4 +.SH NAME +opstart \- start OProfile profiling +.SH SYNOPSIS +.br +.B opstart +.SH DESCRIPTION +.B opstart +is a simple optimised command to start profiling with 2.6 Linux kernels. +OProfile should have already been initialised by calling "opcontrol --start-daemon". + +.SH ENVIRONMENT +No special environment variables are recognised by opstart. + +.SH FILES +.TP +.I /var/lib/oprofile/samples/ +The location of the generated sample files. + +.SH VERSION +.TP +This man page is current for @PACKAGE@-@VERSION@. + +.SH SEE ALSO +.BR @OP_DOCDIR@, +.BR oprofile(1) Index: oprofile/doc/opstop.1.in =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/doc/opstop.1.in 2007-09-28 12:08:30.000000000 +0100 @@ -0,0 +1,28 @@ +.TH OPSTOP 1 "@DATE@" "oprofile @VERSION@" +.UC 4 +.SH NAME +opstop \- stop OProfile profiling +.SH SYNOPSIS +.br +.B opstop +.SH DESCRIPTION +.B opstop +is a simple optimsed command to stop profiling with 2.6 Linux kernels. +You need to run "opcontrol --dump" before being able to view a profile +with opreport. + +.SH ENVIRONMENT +No special environment variables are recognised by opstop. + +.SH FILES +.TP +.I /var/lib/oprofile/samples/ +The location of the generated sample files. + +.SH VERSION +.TP +This man page is current for @PACKAGE@-@VERSION@. + +.SH SEE ALSO +.BR @OP_DOCDIR@, +.BR oprofile(1) |
From: Richard P. <rp...@rp...> - 2007-09-28 13:37:26
|
On smaller systems the overhead of the opcontrol scripts is not insignificant so I've implemented some lightweight start and stop commands. The idea is you'd run "opcontrol --start-daemon" to setup oprofile but then "opstart" can start the profile at a more precise moment. "opstop" stops profiling in a similar way with minimal overhead but isn't 100% equivalent to "opcontrol --stop" since it doesn't dump the data. One possible drawback is they're only implemented to work with 2.6 kernels (and print a warning otherwise). Are these commands of general interest? I've attached a patch so people can experiment... Richard --- ChangeLog | 7 +++ configure.in | 3 + doc/Makefile.am | 2 + doc/opstart.1.in | 27 +++++++++++++ doc/opstop.1.in | 28 ++++++++++++++ utils/Makefile.am | 9 ++++ utils/opstart.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 180 insertions(+), 1 deletion(-) Index: oprofile/utils/Makefile.am =================================================================== --- oprofile.orig/utils/Makefile.am 2007-09-28 11:55:01.000000000 +0100 +++ oprofile/utils/Makefile.am 2007-09-28 11:55:47.000000000 +0100 @@ -3,8 +3,15 @@ AM_CFLAGS = @OP_CFLAGS@ LIBS=@POPT_LIBS@ @LIBERTY_LIBS@ -bin_PROGRAMS = ophelp +bin_PROGRAMS = ophelp opstart dist_bin_SCRIPTS = opcontrol ophelp_SOURCES = ophelp.c ophelp_LDADD = ../libop/libop.a ../libutil/libutil.a + +opstart_SOURCES = opstart.c + +install-exec-local: + cd $(DESTDIR)/$(bindir) && \ + rm -f opstop && \ + $(LN_S) opstart opstop Index: oprofile/utils/opstart.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/utils/opstart.c 2007-09-28 11:55:47.000000000 +0100 @@ -0,0 +1,105 @@ +/** + * @file opstart.c + * Start/Stop oprofile + * + * @remark Copyright 2007 Openedhand Ltd. + * @remark Read the file COPYING + * + * @author Richard Purdie + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +int main(const int argc, const char* argv[]) +{ + const char *enable = "/dev/oprofile/enable"; + const char *lockfile; + unsigned long dpid; + struct stat sbuf; + FILE *lfile, *efile; + int sig, enb, err; + + lockfile = getenv("LOCK_FILE"); + if (!lockfile) + lockfile = "/var/lib/oprofile/lock"; + + /* Add SESSION_DIR support? */ + + if (geteuid()) { + printf("Error: This program must be run as root.\n"); + return 1; + } + + if (stat(enable, &sbuf)) { + printf("Error: Could not find /dev/oprofile/enable, the" + " kernel module probably isn't loaded.\n"); + printf("This binary only works with 2.6 kernels and oprofile" + " must have been initialised with 'opcontrol --start-daemon'.\n"); + return 1; + } + + if (stat(lockfile, &sbuf)) { + printf("Error: Could not find lockfile %s.\n", lockfile); + printf("The oprofile daemon must be running (oprofile must" + " have been initialised with 'opcontrol --start-daemon').\n"); + return 1; + } + + lfile = fopen(lockfile, "r"); + if (!lfile) { + printf("Error opening lockfile %s.\n", lockfile); + return 1; + } + + err = fscanf(lfile, "%ud", &dpid); + if (err != 1) { + printf("Error reading pid from lockfile %s.\n", lockfile); + return 1; + } + fclose(lfile); + + efile = fopen(enable, "r"); + if (!efile) { + printf("Error opening %s.\n", enable); + return 1; + } + + if (strstr(argv[0], "opstart")) { + printf("Starting Profiler\n"); + sig = SIGUSR1; + enb = 1; + } else if (strstr(argv[0], "opstop")) { + printf("Stopping Oprofile.\n"); + printf("You need to run 'opcontrol --dump' when the session" + " is finished.\n"); + sig = SIGUSR2; + enb = 0; + } else { + printf("Error: Please call as 'opstart' or 'opstop'\n"); + return 1; + } + + err = kill(dpid, 0); + if (err) { + printf("Error sending signal to oprofiled. Stale lockfile" + " (%s) ?\n", lockfile); + return 1; + } + + fprintf(efile, "%d\n", enb); + err = kill(dpid, sig); + if (err) { + printf("Error sending signal to oprofiled. Stale lockfile" + " (%s) ?\n", lockfile); + return 1; + } + + return 0; +} + Index: oprofile/configure.in =================================================================== --- oprofile.orig/configure.in 2007-09-28 11:55:01.000000000 +0100 +++ oprofile/configure.in 2007-09-28 12:06:28.000000000 +0100 @@ -16,6 +16,7 @@ AM_INIT_AUTOMAKE(oprofile, 0.9.4cvs) AM_CONFIG_HEADER(config.h) AC_PROG_RANLIB +AC_PROG_LN_S dnl for the man page DATE="`date '+%a %d %B %Y'`" @@ -227,6 +228,8 @@ AC_OUTPUT(Makefile \ doc/xsl/catalog-1.xml \ doc/oprofile.1 \ doc/opcontrol.1 \ + doc/opstart.1 \ + doc/opstop.1 \ doc/ophelp.1 \ doc/opreport.1 \ doc/opannotate.1 \ Index: oprofile/ChangeLog =================================================================== --- oprofile.orig/ChangeLog 2007-09-28 11:55:35.000000000 +0100 +++ oprofile/ChangeLog 2007-09-28 11:56:51.000000000 +0100 @@ -1,5 +1,12 @@ 2007-09-28 Richard Purdie <rp...@op...> + * configure.in: + * utils/Makefile.am: + * utils/opstart.c: Add opstart/opstop commands to minimise overhead + in starting/stopping profiling + +2007-09-28 Richard Purdie <rp...@op...> + * events/arm/armv6/events: Fix armv6 events to match mainline kernels 2007-09-25 Brian Twichell <tb...@us...> Index: oprofile/doc/Makefile.am =================================================================== --- oprofile.orig/doc/Makefile.am 2007-09-28 12:05:02.000000000 +0100 +++ oprofile/doc/Makefile.am 2007-09-28 12:05:26.000000000 +0100 @@ -11,6 +11,8 @@ STYLESHEETS=$(CHUNK_XHTML_STYLESHEET) $( man_MANS = \ oprofile.1 \ opcontrol.1 \ + opstart.1 \ + opstop.1 \ opreport.1 \ opannotate.1 \ opgprof.1 \ Index: oprofile/doc/opstart.1.in =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/doc/opstart.1.in 2007-09-28 12:08:14.000000000 +0100 @@ -0,0 +1,27 @@ +.TH OPSTART 1 "@DATE@" "oprofile @VERSION@" +.UC 4 +.SH NAME +opstart \- start OProfile profiling +.SH SYNOPSIS +.br +.B opstart +.SH DESCRIPTION +.B opstart +is a simple optimised command to start profiling with 2.6 Linux kernels. +OProfile should have already been initialised by calling "opcontrol --start-daemon". + +.SH ENVIRONMENT +No special environment variables are recognised by opstart. + +.SH FILES +.TP +.I /var/lib/oprofile/samples/ +The location of the generated sample files. + +.SH VERSION +.TP +This man page is current for @PACKAGE@-@VERSION@. + +.SH SEE ALSO +.BR @OP_DOCDIR@, +.BR oprofile(1) Index: oprofile/doc/opstop.1.in =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ oprofile/doc/opstop.1.in 2007-09-28 12:08:30.000000000 +0100 @@ -0,0 +1,28 @@ +.TH OPSTOP 1 "@DATE@" "oprofile @VERSION@" +.UC 4 +.SH NAME +opstop \- stop OProfile profiling +.SH SYNOPSIS +.br +.B opstop +.SH DESCRIPTION +.B opstop +is a simple optimsed command to stop profiling with 2.6 Linux kernels. +You need to run "opcontrol --dump" before being able to view a profile +with opreport. + +.SH ENVIRONMENT +No special environment variables are recognised by opstop. + +.SH FILES +.TP +.I /var/lib/oprofile/samples/ +The location of the generated sample files. + +.SH VERSION +.TP +This man page is current for @PACKAGE@-@VERSION@. + +.SH SEE ALSO +.BR @OP_DOCDIR@, +.BR oprofile(1) |
From: John L. <le...@mo...> - 2007-09-28 17:45:26
|
On Fri, Sep 28, 2007 at 12:24:44PM +0100, Richard Purdie wrote: > On smaller systems the overhead of the opcontrol scripts is not > insignificant so I've implemented some lightweight start and stop > commands. The idea is you'd run "opcontrol --start-daemon" to setup I'm confused. Can't you make an opcontrol fast path for start and stop? What exactly is so slow? cheers john |
From: Richard P. <rp...@rp...> - 2007-09-28 21:38:29
|
On Fri, 2007-09-28 at 18:45 +0100, John Levon wrote: > On Fri, Sep 28, 2007 at 12:24:44PM +0100, Richard Purdie wrote: > > > On smaller systems the overhead of the opcontrol scripts is not > > insignificant so I've implemented some lightweight start and stop > > commands. The idea is you'd run "opcontrol --start-daemon" to setup > > I'm confused. Can't you make an opcontrol fast path for start and stop? > What exactly is so slow? There are two ways of handling this, one is to optimise opcontrol, the other is to write the fast path directly in C. With opcontrol its shell script which has more overhead than C before you start. The number of forks or other syscalls required before it reaches the point where the trace starts is significant due to the nature of shell script and I doubt I'd ever be able to remove them all. The same applies to the stop command. Trying to optimise the shell script, there are two more potential issues: 1. Someone can easily and inadvertently introduce overhead in the future 2. The behaviour might need to change for starting and stopping to make it optimal. The opstart/opstop approach I proposed addresses both points. If you want an illustration of what I'm talking about try stracing opcontrol. The opstart/opstop commands are a *lot* cleaner... Cheers, Richard |
From: John L. <le...@mo...> - 2007-09-29 16:25:14
|
On Fri, Sep 28, 2007 at 10:38:20PM +0100, Richard Purdie wrote: > With opcontrol its shell script which has more overhead than C before > you start. The number of forks or other syscalls required before it > reaches the point where the trace starts is significant due to the > nature of shell script and I doubt I'd ever be able to remove them all. > The same applies to the stop command. I find it really hard to believe that oprofile runs on a system where a fast-pathed shell script is so much slower than a C program. > 1. Someone can easily and inadvertently introduce overhead in the future That applies to every improvement ever made, and thus is irrelevant... > 2. The behaviour might need to change for starting and stopping to make > it optimal. That might be ok, for example via opcontrol --fast or something. regards john |
From: Richard P. <rp...@rp...> - 2007-09-29 20:54:12
|
On Sat, 2007-09-29 at 17:25 +0100, John Levon wrote: > On Fri, Sep 28, 2007 at 10:38:20PM +0100, Richard Purdie wrote: > > > With opcontrol its shell script which has more overhead than C before > > you start. The number of forks or other syscalls required before it > > reaches the point where the trace starts is significant due to the > > nature of shell script and I doubt I'd ever be able to remove them all. > > The same applies to the stop command. > > I find it really hard to believe that oprofile runs on a system where a > fast-pathed shell script is so much slower than a C program. Consider the first things the current opcontrol script does. The first call is to check_options early which contains: arg=`printf %s $i | awk -F= '{print $1}'` val=`printf %s $i | awk -F= '{print $2}'` which is 4 forks. The check_version() which follows has an exec call for grep. do_options() has four forks per loop and so on. Exec/fork is slow on ARM and common actions in most shell scripts rely on them quite heavily. They're also going to trigger binaries/libraries loads which interfere with what we're really interested in with oprofile. Now I guess we could add checks before the above to see if we were doing a "--start --fast" or a "--stop --fast" but I'm not sure the result will look particularly good, be particularly maintainable and any implementation is always going to have more overhead than the C version. > > 1. Someone can easily and inadvertently introduce overhead in the future > > That applies to every improvement ever made, and thus is irrelevant... My point is that shell script encourages people to use exec/fork inducing syntax and maintaining the optimised paths will need more effort than any 'normal' improvement. > > 2. The behaviour might need to change for starting and stopping to make > > it optimal. > > That might be ok, for example via opcontrol --fast or something. That could work but it still doesn't feel like the right approach to me... Cheers, Richard |
From: John L. <le...@mo...> - 2007-09-29 21:46:50
|
On Sat, Sep 29, 2007 at 09:54:03PM +0100, Richard Purdie wrote: > My point is that shell script encourages people to use exec/fork > inducing syntax and maintaining the optimised paths will need more > effort than any 'normal' improvement. Are you really suggesting that a clear fast-path with a relevant comment will just be ignored? john |
From: Richard P. <rp...@rp...> - 2007-09-30 10:00:16
|
On Sat, 2007-09-29 at 22:46 +0100, John Levon wrote: > On Sat, Sep 29, 2007 at 09:54:03PM +0100, Richard Purdie wrote: > > > My point is that shell script encourages people to use exec/fork > > inducing syntax and maintaining the optimised paths will need more > > effort than any 'normal' improvement. > > Are you really suggesting that a clear fast-path with a relevant comment > will just be ignored? It really depends what this fast-path looks like. The ones I can picture wouldn't be particularly clear if they try to reuse existing code. The clearest versions would be so isolated from the rest of the opcontrol code they might as well be standalone. Cheers, Richard |