summaryrefslogtreecommitdiffstats
path: root/kstartperf
diff options
context:
space:
mode:
Diffstat (limited to 'kstartperf')
-rw-r--r--kstartperf/Makefile.am14
-rw-r--r--kstartperf/README31
-rw-r--r--kstartperf/kstartperf.cpp124
-rw-r--r--kstartperf/libkstartperf.c122
4 files changed, 291 insertions, 0 deletions
diff --git a/kstartperf/Makefile.am b/kstartperf/Makefile.am
new file mode 100644
index 00000000..9214d389
--- /dev/null
+++ b/kstartperf/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkstartperf.la
+libkstartperf_la_LDFLAGS = $(all_libraries) -version-info 1:0 -no-undefined
+# libkstartperf_la_LIBADD = ../libltdl/libltdlc.la
+libkstartperf_la_SOURCES = libkstartperf.c
+
+bin_PROGRAMS = kstartperf
+kstartperf_LDFLAGS = $(all_libraries)
+kstartperf_LDADD = $(LIB_KDECORE)
+kstartperf_SOURCES = kstartperf.cpp
+
+messages:
+ $(XGETTEXT) $(kstartperf_SOURCES) -o $(podir)/kstartperf.pot
diff --git a/kstartperf/README b/kstartperf/README
new file mode 100644
index 00000000..ff986444
--- /dev/null
+++ b/kstartperf/README
@@ -0,0 +1,31 @@
+
+** kstartperf: startup time measurement for KDE apps **
+
+** Usage:
+
+kstartperf measures startup time for KDE applications. Usage is simple:
+
+ $ kstartperf konsole
+
+will show you the startup time of konsole in milliseconds.
+
+
+** How does it work?
+
+1. Kstartperf stores the current time with microsecond resolution in an
+ environment variable ($KSTARTPERF).
+2. Kstartperf executes the requested application, but with a LD_PRELOAD
+ library that overrides the X11 XMapWindow() function.
+3. As soon as the app calls XMapWindow (this is the point where we assume
+ that the app has "started up"), our function is called instead of the
+ original XMapWindow(). This function calculates the time difference
+ between the current time and the time stored in the environment variable
+ and prints this information to standard error.
+4. Our function disables itself and calls the original XMapWindow().
+
+** Notes
+
+The appliation that is being profiled, needs to be linked against kdecore.
+
+Geert Jansen <jansen@kde.org>,
+20 July 2000
diff --git a/kstartperf/kstartperf.cpp b/kstartperf/kstartperf.cpp
new file mode 100644
index 00000000..3f029b62
--- /dev/null
+++ b/kstartperf/kstartperf.cpp
@@ -0,0 +1,124 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ * $Id$
+ *
+ * This file is part of the KDE project, module kstartperf.
+ * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
+ *
+ * You can freely redistribute this program under the "Artistic License".
+ * See the file "LICENSE.readme" for the exact terms.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <qstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+
+static KCmdLineOptions options[] =
+{
+ { "+command", I18N_NOOP("Specifies the command to run"), 0 },
+ KCmdLineLastOption
+};
+
+
+QString libkstartperf()
+{
+ QString lib = QString::null;
+ QString la_file = locate("lib", "libkstartperf.la");
+
+ if (la_file.isEmpty())
+ return lib;
+
+ // Find the name of the .so file by reading the .la file
+ QFile la(la_file);
+ if (la.open(IO_ReadOnly))
+ {
+ QTextStream is(&la);
+ QString line;
+
+ while (!is.atEnd())
+ {
+ line = is.readLine();
+ if (line.left(15) == "library_names='")
+ {
+ lib = line.mid(15);
+ int pos = lib.find(" ");
+ if (pos > 0)
+ lib = lib.left(pos);
+ }
+ }
+
+ la.close();
+ }
+
+ // Look up the actual .so file.
+ lib = locate("lib", lib);
+ return lib;
+}
+
+
+int main(int argc, char **argv)
+{
+ KAboutData aboutData("kstartperf", I18N_NOOP("KStartPerf"),
+ "1.0", I18N_NOOP("Measures start up time of a KDE application"),
+ KAboutData::License_Artistic,
+ "Copyright (c) 2000 Geert Jansen and libkmapnotify authors");
+ aboutData.addAuthor("Geert Jansen", I18N_NOOP("Maintainer"),
+ "jansen@kde.org", "http://www.stack.nl/~geertj/");
+
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KCmdLineArgs::addCmdLineOptions(options);
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ KApplication *app = new KApplication(false, false);
+
+ // Check arguments
+
+ if (args->count() == 0)
+ {
+ fprintf(stderr, "No command specified!\n");
+ fprintf(stderr, "usage: kstartperf command [arguments]\n");
+ exit(1);
+ }
+
+ // Build command
+
+ char cmd[1024];
+ sprintf(cmd, "LD_PRELOAD=%s %s", libkstartperf().latin1(), args->arg(0));
+ for (int i=1; i<args->count(); i++)
+ {
+ strcat(cmd, " ");
+ strcat(cmd, args->arg(i));
+ }
+
+ // Put the current time in the environment variable `KSTARTPERF'
+
+ struct timeval tv;
+ if (gettimeofday(&tv, 0L) != 0)
+ {
+ perror("gettimeofday()");
+ exit(1);
+ }
+ char env[100];
+ sprintf(env, "KSTARTPERF=%ld:%ld", tv.tv_sec, tv.tv_usec);
+ putenv(env);
+
+ // And exec() the command
+
+ execl("/bin/sh", "sh", "-c", cmd, (void *)0);
+
+ perror("execl()");
+ exit(1);
+}
diff --git a/kstartperf/libkstartperf.c b/kstartperf/libkstartperf.c
new file mode 100644
index 00000000..3c8deae0
--- /dev/null
+++ b/kstartperf/libkstartperf.c
@@ -0,0 +1,122 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ * $Id$
+ *
+ * libkstartperf.c: LD_PRELOAD library for startup time measurements.
+ *
+ * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
+ *
+ * Based heavily on kmapnotify.c:
+ *
+ * (C) 2000 Rik Hemsley <rik@kde.org>
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * (C) 2000 Bill Soudan <soudan@kde.org>
+ */
+
+#include <sys/time.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+
+#include <ltdl.h>
+
+
+/* Prototypes */
+
+int XMapWindow(Display *, Window);
+int XMapRaised(Display *, Window);
+void KDE_InterceptXMapRequest(Display *, Window);
+void KDE_ShowPerformance();
+
+/* Globals */
+
+typedef Window (*KDE_XMapRequestSignature)(Display *, Window);
+KDE_XMapRequestSignature KDE_RealXMapWindow = 0L;
+KDE_XMapRequestSignature KDE_RealXMapRaised = 0L;
+
+
+/* Functions */
+
+int XMapWindow(Display * d, Window w)
+{
+ if (KDE_RealXMapWindow == 0L)
+ {
+ KDE_InterceptXMapRequest(d, w);
+ KDE_ShowPerformance();
+ }
+ return KDE_RealXMapWindow(d, w);
+}
+
+int XMapRaised(Display * d, Window w)
+{
+ if (KDE_RealXMapRaised == 0L)
+ {
+ KDE_InterceptXMapRequest(d, w);
+ KDE_ShowPerformance();
+ }
+ return KDE_RealXMapRaised(d, w);
+}
+
+void KDE_InterceptXMapRequest(Display * d, Window w)
+{
+ lt_dlhandle handle;
+
+ handle = lt_dlopen("libX11.so");
+ if (handle == 0L)
+ handle = lt_dlopen("libX11.so.6");
+
+ if (handle == 0L)
+ {
+ fprintf(stderr, "kstartperf: Could not dlopen libX11\n");
+ exit(1);
+ }
+
+ KDE_RealXMapWindow = (KDE_XMapRequestSignature)lt_dlsym(handle, "XMapWindow");
+ if (KDE_RealXMapWindow == 0L)
+ {
+ fprintf(stderr, "kstartperf: Could not find symbol XMapWindow in libX11\n");
+ exit(1);
+ }
+
+ KDE_RealXMapRaised = (KDE_XMapRequestSignature)lt_dlsym(handle, "XMapRaised");
+ if (KDE_RealXMapRaised == 0L)
+ {
+ fprintf(stderr, "kstartperf: Could not find symbol XMapRaised in libX11\n");
+ exit(1);
+ }
+}
+
+void KDE_ShowPerformance()
+{
+ char *env;
+ long l1, l2;
+ float dt;
+ struct timeval tv;
+
+ env = getenv("KSTARTPERF");
+ if (env == 0L)
+ {
+ fprintf(stderr, "kstartperf: $KSTARTPERF not set!\n");
+ exit(1);
+ }
+ if (sscanf(env, "%ld:%ld", &l1, &l2) != 2)
+ {
+ fprintf(stderr, "kstartperf: $KSTARTPERF illegal format\n");
+ exit(1);
+ }
+
+ if (gettimeofday(&tv, 0L) != 0)
+ {
+ fprintf(stderr, "kstartperf: gettimeofday() failed.\n");
+ exit(1);
+ }
+
+ dt = 1e3*(tv.tv_sec - l1) + 1e-3*(tv.tv_usec - l2);
+ fprintf(stderr, "\nkstartperf: measured startup time at %7.2f ms\n\n", dt);
+}
+