summaryrefslogtreecommitdiffstats
path: root/runtime/bench2
diff options
context:
space:
mode:
authorhunt <hunt>2006-03-09 08:48:06 +0000
committerhunt <hunt>2006-03-09 08:48:06 +0000
commit68642a15584f9e4fbf8cfc5765a3cfaeac0a5bbb (patch)
tree456b5d73292446a4017fcecf5162e5b20be86e95 /runtime/bench2
parent43efac911763c31250e953fcd633d7f275d88270 (diff)
downloadsystemtap-steved-68642a15584f9e4fbf8cfc5765a3cfaeac0a5bbb.tar.gz
systemtap-steved-68642a15584f9e4fbf8cfc5765a3cfaeac0a5bbb.tar.xz
systemtap-steved-68642a15584f9e4fbf8cfc5765a3cfaeac0a5bbb.zip
2006-03-09 Martin Hunt <hunt@redhat.com>
* bench2: New directory containing a benchmark framework.
Diffstat (limited to 'runtime/bench2')
-rw-r--r--runtime/bench2/Makefile7
-rw-r--r--runtime/bench2/README26
-rw-r--r--runtime/bench2/a.st13
-rw-r--r--runtime/bench2/b.st16
-rw-r--r--runtime/bench2/bench.rb225
-rw-r--r--runtime/bench2/itest.c59
-rw-r--r--runtime/bench2/results.txt32
-rwxr-xr-xruntime/bench2/run_bench40
-rwxr-xr-xruntime/bench2/stap_bench16
9 files changed, 434 insertions, 0 deletions
diff --git a/runtime/bench2/Makefile b/runtime/bench2/Makefile
new file mode 100644
index 00000000..7fcfcfe4
--- /dev/null
+++ b/runtime/bench2/Makefile
@@ -0,0 +1,7 @@
+all: itest
+
+itest: itest.c
+ gcc -Wall -O3 -o itest itest.c
+
+clean:
+ /bin/rm -f itest
diff --git a/runtime/bench2/README b/runtime/bench2/README
new file mode 100644
index 00000000..626d4675
--- /dev/null
+++ b/runtime/bench2/README
@@ -0,0 +1,26 @@
+This is a framework for profiling systemtap scripts and the
+underlying runtime functions.
+
+To try the tests:
+>make
+./run_bench
+./stap_bench
+
+You will need ruby installed. "yum install ruby" or "up2date ruby" to get it.
+
+---- FILES ----
+a.st - sample script test file
+b.st - sample script test file
+
+itest.c - used by tests. Type "make" to build
+Makefile - makefile for itest
+
+run_bench - test driver with some test scripts. Tests may
+be supplied in files (as in a.st and b.st) or in strings, as
+in this example.
+
+stap_bench - test driver that tests all files ending in ".st"
+
+bench.rb - bench classes used by drivers.
+
+results.txt - Some results of "run_bench" on different machines.
diff --git a/runtime/bench2/a.st b/runtime/bench2/a.st
new file mode 100644
index 00000000..2efc771f
--- /dev/null
+++ b/runtime/bench2/a.st
@@ -0,0 +1,13 @@
+# printf probefunc
+
+# You can put initialization in here
+probe begin {
+ printf("BEGIN\n")
+}
+
+# This gets probed millions of times. TEST gets replaces
+# by the real probe point.
+probe TEST {
+ printf("%s\n",probefunc())
+}
+
diff --git a/runtime/bench2/b.st b/runtime/bench2/b.st
new file mode 100644
index 00000000..687f1a8f
--- /dev/null
+++ b/runtime/bench2/b.st
@@ -0,0 +1,16 @@
+# printf execname
+
+# You can put initialization in here
+probe begin {
+ printf("FOO\n")
+}
+
+# This gets probed millions of times. TEST gets replaces
+# by the real probe point.
+probe TEST {
+ printf("%s\n", execname())
+}
+
+probe end {
+ printf("DONE\n")
+}
diff --git a/runtime/bench2/bench.rb b/runtime/bench2/bench.rb
new file mode 100644
index 00000000..2c21b381
--- /dev/null
+++ b/runtime/bench2/bench.rb
@@ -0,0 +1,225 @@
+class Bench
+ def initialize(desc)
+ @desc = desc
+ @code = nil
+ @file = nil
+ @failures = ""
+ @results = 0
+ if @@printed_header == 0
+ print_header
+ end
+ if @@ftime == 0
+ @@ftime = `./itest 5`.to_i
+ end
+ if @@stpd.nil?
+ for path in ['/usr/libexec/systemtap/stpd', '/usr/local/libexec/systemtap/stpd']
+ if File.exist?(path)
+ @@stpd = path
+ break
+ end
+ end
+ end
+ if @@runtime.nil?
+ for path in ['/usr/share/systemtap/runtime', '/usr/local/share/systemtap/runtime']
+ if File.exist?(path)
+ @@runtime = path
+ break
+ end
+ end
+ end
+ end
+
+ attr_writer :code, :file
+ attr_reader :failures, :results
+
+ def run
+ Signal.trap("INT") do
+ cleanup
+ exit
+ end
+ compile
+ load
+ @results = `./itest 1`.to_i - @@ftime
+ sleep 5
+ `sudo killall -HUP stpd`
+ `tail #{@dir}/xxx > #{@dir}/xxx.out`
+ File.open("#{@dir}/xxx.out") do |file|
+ file.each_line {|line| @failures += line if line =~ /WARNING/}
+ end
+ Process.wait
+ cleanup
+ end
+
+ def print
+ if @results
+ printf("runtime: %-20s\t%d\n", @desc, @results)
+ end
+ end
+
+ private
+ @dir = nil
+
+ protected
+
+ # function call overhead
+ @@ftime = 0
+ @@printed_header = 0
+ @@stpd = nil
+ @@runtime = nil
+
+ def cleanup
+ `/bin/rm -f stap.out` if File.exists?("stap.out")
+ `/bin/rm -f bench.stp` if File.exists?("bench.stp")
+ `/bin/rm -rf #{@dir}` unless @dir.nil?
+ end
+
+ def load
+ fork do exec "sudo #{@@stpd} -rmq #{@dir}/bench.ko > #{@dir}/xxx" end
+ sleep 5
+ end
+
+ def compile
+ @dir = `mktemp -dt benchXXXXX`.strip
+ emit_code
+ modules = "/lib/modules/" + `uname -r`.strip + "/build"
+ res=`make -C \"#{modules}\" M=\"#{@dir}\" modules V=1`
+ if !File.exist?("#{@dir}/bench.ko")
+ puts res
+ cleanup
+ exit
+ end
+ end
+
+ def emit_code
+ if @code
+ begin
+ f = File.new("#{@dir}/bench.c","w")
+ f << "#include \"runtime.h\"
+#include \"probes.c\"\n
+MODULE_DESCRIPTION(\"SystemTap probe: bench\");
+MODULE_AUTHOR(\"automatically generated by bench2/run_bench\");\n\n"
+ f << "static int inst_sys_getuid (struct kprobe *p, struct pt_regs *regs) {\n"
+ f << @code
+ f << "\n return 0;\n}
+static struct kprobe kp[] = {\n {\n .addr = \"sys_getuid\",
+ .pre_handler = inst_sys_getuid\n }\n};\n
+#define NUM_KPROBES 1\n
+int probe_start(void)\n{\n return _stp_register_kprobes (kp, NUM_KPROBES);\n}\n
+void probe_exit (void)\n{\n _stp_unregister_kprobes (kp, NUM_KPROBES); \n}\n"
+ rescue
+ puts "Error writing source file"
+ ensure
+ f.close unless f.nil?
+ end
+ makefile = File.new("#{@dir}/Makefile","w")
+ makefile << "CFLAGS += -Wno-unused -Werror
+CFLAGS += -I \"#{@@runtime}\"
+obj-m := bench.o
+"
+ makefile.close
+ else
+ puts "NO CODE!"
+ end
+ end
+
+ def print_header
+ @@printed_header = 1
+ nproc=`grep ^processor /proc/cpuinfo`.count("\n")
+ physical_cpus=`grep "physical id" /proc/cpuinfo`.split("\n").uniq.length
+ model=`grep "model name" /proc/cpuinfo`.match(/(model name\t: )([^\n]*)/)[2]
+ puts "SystemTap BENCH2 \t" + `date`
+ puts "kernel: " + `uname -r`.strip + " " + `uname -m`.strip
+ begin
+ puts IO.read("/etc/redhat-release")
+ rescue
+ end
+
+ puts `uname -n`.strip + ": " + `uptime`
+ if nproc > 1
+ puts "processors: #{nproc} (#{physical_cpus} physical) #{model}"
+ else
+ puts "processors: #{nproc} #{model}"
+ end
+
+ begin
+ mem=IO.read("/proc/meminfo").split("\n")
+ puts mem[0] + "\t" + mem[1]
+ rescue
+ end
+ puts "-"*64
+ check_cpuspeed
+ @@ftime = `./itest 5`.to_i
+ puts "For comparison, function call overhead is #@@ftime nsecs."
+ puts "Times below are in nanoseconds and include kprobe overhead."
+ puts "-"*64
+ end
+
+ def check_cpuspeed
+ maxfile = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"
+ minfile = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
+ if File.exist?(maxfile)
+ maxfreq = `cat #{maxfile}`.to_i
+ minfreq = `cat #{minfile}`.to_i
+ if minfreq != maxfreq
+ `sudo /bin/sh -c \"echo #{maxfreq} > #{minfile}\"`
+ puts "CPU frequency scaling detected and disabled."
+ puts "After testing, enable it again by typing (as root)"
+ puts "echo #{minfreq} > #{minfile}"
+ puts "-"*64
+ end
+ end
+ end
+end
+
+class Stapbench < Bench
+ def print
+ if @results
+ printf("script : %-20s\t%d\n", @desc, @results)
+ end
+ end
+
+ protected
+
+ def load
+ # we do this in several steps because the compilation phase can take a long time
+ `stap -kvvp4 -m bench bench.stp &> stap.out`
+ IO.foreach("stap.out") {|line| @dir = line if line =~ /Created temporary directory/}
+ @dir = @dir.match(/"([^"]*)/)[1]
+ if !File.exist?("#{@dir}/bench.ko")
+ puts `cat stap.out`
+ cleanup
+ exit
+ end
+ fork do exec "sudo #{@@stpd} -rmq #{@dir}/bench.ko > #{@dir}/xxx" end
+ sleep 5
+ end
+
+ def compile
+ emit_code
+ end
+
+ def emit_code
+ if @file
+ File.open("bench.stp","w") do |b|
+ File.open(@file,"r") do |f|
+ f.each_line do |line|
+ b.puts(line.sub(/TEST/,'kernel.function("sys_getuid")'))
+ end
+ end
+ end
+ elsif @code
+ begin
+ f = File.new("bench.stp","w")
+ f << "probe kernel.function(\"sys_getuid\") {\n"
+ f << @code
+ f << "\n}\n"
+ rescue
+ puts "Error writing source file"
+ ensure
+ f.close unless f.nil?
+ end
+ else
+ puts "NO CODE!"
+ end
+ end
+end
diff --git a/runtime/bench2/itest.c b/runtime/bench2/itest.c
new file mode 100644
index 00000000..dc385567
--- /dev/null
+++ b/runtime/bench2/itest.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+typedef unsigned long long uint64;
+struct timeval tstart, tstop;
+
+void start()
+{
+ gettimeofday (&tstart, NULL);
+}
+
+uint64 usecs (struct timeval *tv)
+{
+ return tv->tv_sec * 1000000 + tv->tv_usec;
+}
+
+uint64 stop()
+{
+ gettimeofday (&tstop, NULL);
+ return usecs(&tstop) - usecs(&tstart);
+}
+
+void usage(char *name)
+{
+ printf ("Usage %s [time]\nWhere \"time\" is millions of times to loop.\n", name);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, n = 1;
+ uint64 nsecs;
+
+ if (argc > 2)
+ usage(argv[0]);
+
+ if (argc == 2) {
+ n = strtol(argv[1], NULL, 10);
+ if (n == 0)
+ usage(argv[0]);
+ }
+
+
+ start();
+ for (i = 0; i < n * 1000000; i++)
+ getuid();
+
+ nsecs = stop() / (n * 1000);
+
+ /* returns nanosecs per call */
+ printf("%lld\n", nsecs);
+ return 0;
+}
diff --git a/runtime/bench2/results.txt b/runtime/bench2/results.txt
new file mode 100644
index 00000000..a58f45dd
--- /dev/null
+++ b/runtime/bench2/results.txt
@@ -0,0 +1,32 @@
+SystemTap BENCH2 Thu Mar 9 00:24:53 PST 2006
+kernel: 2.6.15-1.2025_FC5 i686
+Fedora Core release 4.92 (Pre-FC5)
+monkey2: 00:24:53 up 2:48, 3 users, load average: 0.01, 0.05, 0.01
+processors: 1 Intel(R) Pentium(R) M processor 1.70GHz
+MemTotal: 515200 kB MemFree: 73264 kB
+----------------------------------------------------------------
+For comparison, function call overhead is 378 nsecs.
+Times below are in nanoseconds and include kprobe overhead.
+----------------------------------------------------------------
+runtime: empty probe 514
+script : empty probe 543
+runtime: printf 100 chars 1932
+script : printf 100 chars 1947
+runtime: printf 5 integers 3078
+script : printf 5 integers 3127
+SystemTap BENCH2 Thu Mar 9 00:30:12 PST 2006
+kernel: 2.6.15-1.1830_FC4.huntsmp i686
+Fedora Core release 4 (Stentz)
+dragon: 00:30:12 up 3:02, 3 users, load average: 0.00, 0.00, 0.00
+processors: 2 (1 physical) Intel(R) Pentium(R) 4 CPU 2.60GHz
+MemTotal: 2067716 kB MemFree: 1841188 kB
+----------------------------------------------------------------
+For comparison, function call overhead is 795 nsecs.
+Times below are in nanoseconds and include kprobe overhead.
+----------------------------------------------------------------
+runtime: empty probe 1178
+script : empty probe 1372
+runtime: printf 100 chars 2408
+script : printf 100 chars 2504
+runtime: printf 5 integers 4048
+script : printf 5 integers 3590
diff --git a/runtime/bench2/run_bench b/runtime/bench2/run_bench
new file mode 100755
index 00000000..1f868ced
--- /dev/null
+++ b/runtime/bench2/run_bench
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+load './bench.rb'
+
+# runtime test with empty kprobe
+test = Bench.new("empty probe")
+test.code = ""
+test.run
+test.print
+
+# script test with empty probe
+test0 = Stapbench.new("empty probe")
+test0.code = ""
+test0.run
+test0.print
+
+# runtime test to print 100 chars
+test2 = Bench.new("printf 100 chars")
+test2.code = "_stp_printf (\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\");
+ _stp_print_flush();"
+test2.run
+test2.print
+
+# script test to print 100 chars
+test2a = Stapbench.new("printf 100 chars")
+test2a.code = "printf(\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\")"
+test2a.run
+test2a.print
+
+# runtime test to print 5 integers
+test3 = Bench.new("printf 5 integers")
+test3.code = "_stp_printf (\"%lld, %lld, %lld, %lld, %lld\\n\", 1LL, 0xffffLL, 0x8000ffffLL, 0xffff000011112222LL, 0x7000000000000000LL);
+ _stp_print_flush();"
+test3.run
+test3.print
+
+# script test to print 5 integers
+test4 = Stapbench.new("printf 5 integers")
+test4.code = "printf(\"%d, %d, %d, %d, %d\\n\", 1, 0xffff, 0x8000ffff, 0xffff000011112222, 0x7000000000000000)"
+test4.run
+test4.print
diff --git a/runtime/bench2/stap_bench b/runtime/bench2/stap_bench
new file mode 100755
index 00000000..b3b450d8
--- /dev/null
+++ b/runtime/bench2/stap_bench
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+load './bench.rb'
+
+# run tests on all the files ending in ".st"
+# These must be systemtap scripts.
+# First line of scripts must be a comment with the test description.
+
+Dir["*.st"].each do |file|
+ File.open(file,"r") do |f|
+ desc = f.gets.sub(/^#/,'').strip
+ test = Stapbench.new(desc)
+ test.file = file
+ test.run
+ test.print
+ end
+end