Fri Jun 19 17:31:27 CEST 2009 Tobias Rautenkranz * add signal-slot benchmark & better graphs diff -rN -u old-benchmark/CMakeLists.txt new-benchmark/CMakeLists.txt --- old-benchmark/CMakeLists.txt 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/CMakeLists.txt 2014-10-30 07:07:00.000000000 +0100 @@ -2,11 +2,16 @@ set(QT_DONT_USE_QTGUI true) include(${QT_USE_FILE}) +set(CXX_BENCHMARK_SOURCES + benchmark.cpp construct.cpp overload.cpp simple-call.cpp signal_slot.cpp) + +qt4_automoc(signal_slot.cpp) + include(CheckCXXCompilerFlag) check_cxx_compiler_flag("-fvisibility=hidden" CXX_VISIBILITY) if(CXX_VISIBILITY) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden") endif(CXX_VISIBILITY) -add_library(cl-smoke-benchmark MODULE benchmark.cpp construct.cpp overload.cpp simple-call.cpp) +add_library(cl-smoke-benchmark MODULE ${CXX_BENCHMARK_SOURCES}) target_link_libraries(cl-smoke-benchmark ${QT_LIBRARIES}) diff -rN -u old-benchmark/benchmark.cpp new-benchmark/benchmark.cpp --- old-benchmark/benchmark.cpp 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/benchmark.cpp 2014-10-30 07:07:00.000000000 +0100 @@ -6,14 +6,11 @@ extern "C" { -CL_SMOKE_BENCHMARK_EXPORT char +CL_SMOKE_BENCHMARK_EXPORT void cl_smoke_benchmark_byte_array_size(size_t iterations) { - char a; for(size_t i=0; i< iterations; i++) - a += array.at(0); - - return a; + array.at(0); } } // extern "C" diff -rN -u old-benchmark/benchmark.lisp new-benchmark/benchmark.lisp --- old-benchmark/benchmark.lisp 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/benchmark.lisp 2014-10-30 07:07:00.000000000 +0100 @@ -7,7 +7,9 @@ (setf timings args)) function arguments) - (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)))) (defun print-header (stream data) (dolist (d (alexandria:plist-alist (first data))) @@ -22,17 +24,31 @@ (format out "~S~T" (rest e))) (format out "~%")))) +(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)) -(defun benchmark (function &rest args) +(defun benchmark (function iterations) (let ((data)) + (dotimes (n 3) + (funcall function iterations)) ;; startup (dotimes (n 20 data) (sb-ext:gc :full t) - (push (apply #'timing function args) + (push (nconc (list :iterations iterations) + (timing function iterations)) data)))) -(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 "."))) (file (make-pathname :defaults name :type "dat"))) (write-R-table data file) @@ -40,14 +56,18 @@ (make-pathname :defaults file :name (concatenate 'string "cxx-" - (pathname-name file)))))) + (pathname-name file))))) + (terpri)) -(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) (run-compare "inline-call" #'inline-call - #'cl-smoke-benchmark-byte-array-size 1000) + #'cl-smoke-benchmark-byte-array-size 50000 3000) (run-compare "simple-call" #'simple-call - #'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)))) diff -rN -u old-benchmark/benchmark.sh new-benchmark/benchmark.sh --- old-benchmark/benchmark.sh 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/benchmark.sh 2014-10-30 07:07:00.000000000 +0100 @@ -1,5 +1,5 @@ #!/bin/sh rm -- *.dat -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 diff -rN -u old-benchmark/cl-smoke.benchmark.mbd new-benchmark/cl-smoke.benchmark.mbd --- old-benchmark/cl-smoke.benchmark.mbd 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/cl-smoke.benchmark.mbd 2014-10-30 07:07:00.000000000 +0100 @@ -21,7 +21,7 @@ (define-system :cl-smoke.benchmark () (:version 0 0 1) - (:documentation "Benchmark cl-smoke agains C++." + (:documentation "Benchmark cl-smoke agains C++.") (:serial t) (:components "package" diff -rN -u old-benchmark/cxx.lisp new-benchmark/cxx.lisp --- old-benchmark/cxx.lisp 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/cxx.lisp 2014-10-30 07:07:00.000000000 +0100 @@ -3,16 +3,22 @@ (use-foreign-library libcl-smoke-benchmark) (defctype size-t :unsigned-int) -(defcfun cl-smoke-benchmark-byte-array-size :char +(declaim (inline cl-smoke-benchmark-byte-array-size)) +(defcfun cl-smoke-benchmark-byte-array-size :void (iterations size-t)) +(declaim (inline cl-smoke-benchmark-overload)) (defcfun cl-smoke-benchmark-overload :unsigned-int (iterations size-t)) +(declaim (inline cl-smoke-benchmark-signal-slot)) +(defcfun cl-smoke-benchmark-signal-slot :void + (iterations size-t)) (defcfun cl-smoke-benchmark-construct-setup :void (iterations size-t)) +(declaim (inline cl-smoke-benchmark-construct)) (defcfun cl-smoke-benchmark-construct :char (iterations size-t)) diff -rN -u old-benchmark/lisp-benchmark.lisp new-benchmark/lisp-benchmark.lisp --- old-benchmark/lisp-benchmark.lisp 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/lisp-benchmark.lisp 2014-10-30 07:07:00.000000000 +0100 @@ -10,6 +10,7 @@ (setf char (cxx:aref array 0)))))) (let ((object (make-instance 'qt:object))) + (declare (qt:object object)) (defun simple-call (iterations) (declare (fixnum iterations) (optimize (speed 3))) @@ -20,16 +21,17 @@ () (:metaclass cxx:class)) -(defmethod cxx:meta-object ((object my-object)) - (declare (optimize (speed 3))) - nil) -(defun overload (iterations) +(defun signal-slot (iterations) (declare (fixnum iterations) (optimize (speed 3))) - (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 ())) (dotimes (i iterations) - (cxx:meta-object object)))) + (funcall my-signal)))) + (defun construct (iterations) (declare (fixnum iterations) diff -rN -u old-benchmark/package.lisp new-benchmark/package.lisp --- old-benchmark/package.lisp 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/package.lisp 2014-10-30 07:07:00.000000000 +0100 @@ -1,2 +1,3 @@ (defpackage :cl-smoke.benchmark - (:use :cl :cxx-support :cffi)) + (:use :cl :cxx-support :cffi) + (:export #:run)) diff -rN -u old-benchmark/plot.R new-benchmark/plot.R --- old-benchmark/plot.R 2014-10-30 07:07:00.000000000 +0100 +++ new-benchmark/plot.R 2014-10-30 07:07:00.000000000 +0100 @@ -1,31 +1,52 @@ #!/usr/bin/R +round_to_signif <- function(value, deviation) { + round(value, -floor(log(deviation)/log(10))) +} boxplot_benchmark <- function(lisp_data, cxx_data) { + iterations <- lisp_data$ITERATIONS[1] + cxx_iterations <- cxx_data$ITERATIONS[1] + cxx_multiplier <- iterations / cxx_iterations + cxx_mean <- mean(cxx_data$PROCESSOR.CYCLES) - 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), log="y", names=c("C++", "Lisp"), ylab="processor cycles") + 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)) } -pdf("benchmark.pdf") +pdf("benchmark.pdf", title="cl-smoke.benchmark") + +info <- read.table("info.dat", header=TRUE) cxx_simple_call <- read.table("cxx-simple-call.dat", header=TRUE) simple_call <- read.table("simple-call.dat", header=TRUE) boxplot_benchmark(simple_call, cxx_simple_call) -title("Simple Call") +title("Simple Call", + paste(info$TYPE[1], info$VERSION[1], "on", info$OS[1], info$OS.VERSION[1])) cxx_inline_call <- read.table("cxx-inline-call.dat", header=TRUE) inline_call <- read.table("inline-call.dat", header=TRUE) boxplot_benchmark(inline_call, cxx_inline_call) title("Inline Call") -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_construct <- read.table("cxx-construct.dat", header=TRUE) -construct <- read.table("construct.dat", header=TRUE) -boxplot_benchmark(construct, cxx_construct) -title("Construct Class") +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") + +#cxx_construct <- read.table("cxx-construct.dat", header=TRUE) +#construct <- read.table("construct.dat", header=TRUE) +#boxplot_benchmark(construct, cxx_construct) +#title("Construct Class") diff -rN -u old-benchmark/signal_slot.cpp new-benchmark/signal_slot.cpp --- old-benchmark/signal_slot.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new-benchmark/signal_slot.cpp 2014-10-30 07:07:00.000000000 +0100 @@ -0,0 +1,24 @@ +#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 + +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