add signal-slot benchmark & better graphs
Fri Jun 19 17:31:27 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* add signal-slot benchmark & better graphs
hunk ./CMakeLists.txt 5
+set(CXX_BENCHMARK_SOURCES
+ benchmark.cpp construct.cpp overload.cpp simple-call.cpp signal_slot.cpp)
+
+qt4_automoc(signal_slot.cpp)
+
hunk ./CMakeLists.txt 16
-add_library(cl-smoke-benchmark MODULE benchmark.cpp construct.cpp overload.cpp simple-call.cpp)
+add_library(cl-smoke-benchmark MODULE ${CXX_BENCHMARK_SOURCES})
hunk ./benchmark.cpp 9
-CL_SMOKE_BENCHMARK_EXPORT char
+CL_SMOKE_BENCHMARK_EXPORT void
hunk ./benchmark.cpp 12
- char a;
hunk ./benchmark.cpp 13
- a += array.at(0);
-
- return a;
+ array.at(0);
hunk ./benchmark.lisp 10
- (list :processor-cycles (getf timings :processor-cycles))))
+ (list :processor-cycles (getf timings :processor-cycles)
+ :system-run-time-us (getf timings :system-run-time-us)
+ :user-run-time-us (getf timings :user-run-time-us))))
hunk ./benchmark.lisp 27
+(defun write-lisp-info (file)
+ (write-R-table
+ `((:type ,(lisp-implementation-type)
+ :version ,(lisp-implementation-version)
+ :arch ,(machine-type)
+ :os ,(software-type)
+ :os-version ,(software-version)
+ :cl-smoke-version ,(mb.sysdef::version-string (mb.sysdef:version-of (mb.sysdef:find-system :smoke)))))
+ file))
hunk ./benchmark.lisp 37
-(defun benchmark (function &rest args)
+(defun benchmark (function iterations)
hunk ./benchmark.lisp 39
+ (dotimes (n 3)
+ (funcall function iterations)) ;; startup
hunk ./benchmark.lisp 43
- (push (apply #'timing function args)
+ (push (nconc (list :iterations iterations)
+ (timing function iterations))
hunk ./benchmark.lisp 47
-(defun run-compare (name function cxx-function iterations)
- (let ((data (benchmark function iterations))
- (cxx-data (benchmark cxx-function iterations))
+(defun run-compare (name function cxx-function iterations multiplier)
+ (format t "running ~A." name)
+ (let ((data (prog1 (benchmark function iterations) (princ ".")))
+ (cxx-data (prog1 (benchmark cxx-function (* multiplier iterations))
+ (princ ".")))
hunk ./benchmark.lisp 59
- (pathname-name file))))))
+ (pathname-name file)))))
+ (terpri))
hunk ./benchmark.lisp 62
-(defun run ()
- (run-compare "overload" #'overload #'cl-smoke-benchmark-overload 1000)
+(defun run (&optional construct)
+ (write-lisp-info "info.dat")
+ (run-compare "signal-slot" #'signal-slot
+ #'cl-smoke-benchmark-signal-slot 5000 1000)
hunk ./benchmark.lisp 67
- #'cl-smoke-benchmark-byte-array-size 1000)
+ #'cl-smoke-benchmark-byte-array-size 50000 3000)
hunk ./benchmark.lisp 69
- #'cl-smoke-benchmark-simple-call 1000)
- (with-benchmark-cxx-construct (1000)
- (run-compare "construct" #'construct
- #'cl-smoke-benchmark-construct 1000)))
+ #'cl-smoke-benchmark-simple-call 50000 3000)
+ (when construct
+ (with-benchmark-cxx-construct ((* 50 1000))
+ (run-compare "construct" #'construct
+ #'cl-smoke-benchmark-construct 1000 50))))
hunk ./benchmark.sh 4
-sbcl --eval "(mb:load :cl-smoke.benchmark)" --eval "(cl-smoke.benchmark::run)" --eval "(quit)" || exit 1
-R --no-save < ./plot.R
+sbcl --eval "(mb:load :cl-smoke.benchmark)" --eval "(cl-smoke.benchmark:run)" --eval "(quit)" || exit 1
+R --no-save < ./plot.R > /dev/null
hunk ./cl-smoke.benchmark.mbd 24
- (:documentation "Benchmark cl-smoke agains C++."
+ (:documentation "Benchmark cl-smoke agains C++.")
hunk ./cxx.lisp 6
-(defcfun cl-smoke-benchmark-byte-array-size :char
+(declaim (inline cl-smoke-benchmark-byte-array-size))
+(defcfun cl-smoke-benchmark-byte-array-size :void
hunk ./cxx.lisp 10
+(declaim (inline cl-smoke-benchmark-overload))
hunk ./cxx.lisp 14
+(declaim (inline cl-smoke-benchmark-signal-slot))
+(defcfun cl-smoke-benchmark-signal-slot :void
+ (iterations size-t))
hunk ./cxx.lisp 21
+(declaim (inline cl-smoke-benchmark-construct))
hunk ./lisp-benchmark.lisp 13
+ (declare (qt:object object))
hunk ./lisp-benchmark.lisp 24
-(defmethod cxx:meta-object ((object my-object))
- (declare (optimize (speed 3)))
- nil)
hunk ./lisp-benchmark.lisp 25
-(defun overload (iterations)
+(defun signal-slot (iterations)
hunk ./lisp-benchmark.lisp 28
- (let ((object (make-instance 'my-object)))
+ (let ((my-signal (make-instance 'cl-smoke.qt-impl::qsignal :argument-types nil)))
+ (declare (function my-signal))
+ (qt:connect my-signal
+ #'(lambda ()))
hunk ./lisp-benchmark.lisp 33
- (cxx:meta-object object))))
+ (funcall my-signal))))
+ [_$_]
hunk ./package.lisp 2
- (:use :cl :cxx-support :cffi))
+ (:use :cl :cxx-support :cffi)
+ (:export #:run))
hunk ./plot.R 3
+round_to_signif <- function(value, deviation) {
+ round(value, -floor(log(deviation)/log(10)))
+}
hunk ./plot.R 8
+ iterations <- lisp_data$ITERATIONS[1]
+ cxx_iterations <- cxx_data$ITERATIONS[1]
+ cxx_multiplier <- iterations / cxx_iterations
+
hunk ./plot.R 13
- boxplot(c(cxx_data["PROCESSOR.CYCLES"]/cxx_mean, lisp_data["PROCESSOR.CYCLES"]/cxx_mean),
+ scaled_lisp_data <- lisp_data["PROCESSOR.CYCLES"]/cxx_mean/cxx_multiplier;
+ par(mfrow=c(1,2))
+ boxplot(c(cxx_data["PROCESSOR.CYCLES"]/cxx_mean, scaled_lisp_data),
hunk ./plot.R 17
+ axis(4, at=c(round_to_signif(mean(scaled_lisp_data),
+ sd(scaled_lisp_data))))
+
+ cxx_mean <- mean(cxx_data$USER.RUN.TIME.US)
+ scaled_lisp_data <- lisp_data["USER.RUN.TIME.US"]/cxx_mean/cxx_multiplier;
+ boxplot(c(cxx_data["USER.RUN.TIME.US"]/cxx_mean, scaled_lisp_data),
+ log="y", names=c("C++", "Lisp"), ylab="user run time")
+ axis(4, at=c(round_to_signif(mean(scaled_lisp_data),
+ sd(scaled_lisp_data))))
+ par(mfrow=c(1,1))
hunk ./plot.R 29
-pdf("benchmark.pdf")
+pdf("benchmark.pdf", title="cl-smoke.benchmark")
+
+info <- read.table("info.dat", header=TRUE)
hunk ./plot.R 36
-title("Simple Call")
+title("Simple Call",
+ paste(info$TYPE[1], info$VERSION[1], "on", info$OS[1], info$OS.VERSION[1]))
hunk ./plot.R 44
-cxx_overload <- read.table("cxx-overload.dat", header=TRUE)
-overload <- read.table("overload.dat", header=TRUE)
-boxplot_benchmark(overload, cxx_overload)
-title("Overload Virtual Function")
-
+cxx_signal_slot <- read.table("cxx-signal-slot.dat", header=TRUE)
+signal_slot <- read.table("signal-slot.dat", header=TRUE)
+boxplot_benchmark(signal_slot, cxx_signal_slot)
+title("Signal Slot")
hunk ./plot.R 49
-cxx_construct <- read.table("cxx-construct.dat", header=TRUE)
-construct <- read.table("construct.dat", header=TRUE)
-boxplot_benchmark(construct, cxx_construct)
-title("Construct Class")
+#cxx_construct <- read.table("cxx-construct.dat", header=TRUE)
+#construct <- read.table("construct.dat", header=TRUE)
+#boxplot_benchmark(construct, cxx_construct)
+#title("Construct Class")
addfile ./signal_slot.cpp
hunk ./signal_slot.cpp 1
+#include "signal_slot.h"
+#include "signal_slot.moc"
+
+#include "benchmark.h"
+
+void
+signal_object::my_slot()
+{
+}
+
+extern "C" {
+
+CL_SMOKE_BENCHMARK_EXPORT void
+cl_smoke_benchmark_signal_slot(size_t iterations)
+{
+ signal_object object;
+ bool ret = QObject::connect(&object, SIGNAL(my_signal()), &object, SLOT(my_slot()));
+ Q_ASSERT(ret);
+
+ for (size_t i=0; i<iterations; i++)
+ object.emit_my_signal();
+}
+
+} // extern "C"
addfile ./signal_slot.h
hunk ./signal_slot.h 1
+#ifndef CL_SMOKE_BENCHMARK_SIGNAL_SLOT_H
+#define CL_SMOKE_BENCHMARK_SIGNAL_SLOT_H
+
+#include <QObject>
+
+class signal_object : public QObject
+{
+ Q_OBJECT
+ public:
+ void
+ emit_my_signal()
+ { emit my_signal(); }
+
+ signals:
+ void
+ my_signal();
+
+ public slots:
+ void
+ my_slot();
+};
+
+#endif // CL_SMOKE_BENCHMARK_SIGNAL_SLOT_H