initial import --> to head
Sun Jan 10 11:16:40 CET 2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
* ASDF & modular smoke.
Wed Jul 8 17:34:16 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* Benchmark overload resolution at compile time.
Fri Jun 19 17:31:27 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* add signal-slot benchmark & better graphs
Mon May 25 16:59:32 CEST 2009 Tobias Rautenkranz <tobias@rautenkranz.ch>
* initial import
diff -rN -u old-benchmark/CMakeLists.txt new-benchmark/CMakeLists.txt
--- old-benchmark/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/CMakeLists.txt 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,17 @@
+find_package(Qt4)
+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 ${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 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/benchmark.cpp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,16 @@
+#include "benchmark.h"
+
+#include <QByteArray>
+
+static QByteArray array("foobar");
+
+extern "C" {
+
+CL_SMOKE_BENCHMARK_EXPORT void
+cl_smoke_benchmark_byte_array_size(size_t iterations)
+{
+ for(size_t i=0; i< iterations; i++)
+ array.at(0);
+}
+
+} // extern "C"
diff -rN -u old-benchmark/benchmark.lisp new-benchmark/benchmark.lisp
--- old-benchmark/benchmark.lisp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/benchmark.lisp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,76 @@
+(in-package :cl-smoke.benchmark)
+
+(defun timing (function &rest arguments)
+ (let ((timings))
+ (apply #'sb-ext:call-with-timing
+ #'(lambda (&rest args)
+ (setf timings args))
+ function
+ arguments)
+ (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)))
+ (format stream "~A " (first d)))
+ (format stream "~%"))
+
+(defun write-R-table (data file)
+ (with-open-file (out file :direction :output)
+ (print-header out data)
+ (dolist (d data)
+ (dolist (e (alexandria:plist-alist d))
+ (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 ,(format nil "~{~A~^.~}"
+ (asdf:component-version (asdf:find-system :cl-smoke.smoke)))))
+ file))
+
+(defun benchmark (function iterations)
+ (let ((data))
+ (dotimes (n 3)
+ (funcall function iterations)) ;; startup
+ (dotimes (n 20 data)
+ (tg:gc :full t)
+ (push (nconc (list :iterations iterations)
+ (timing function iterations))
+ data))))
+
+(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)
+ (write-R-table cxx-data
+ (make-pathname :defaults file
+ :name (concatenate 'string
+ "cxx-"
+ (pathname-name file)))))
+ (terpri))
+
+(defun run (&optional construct)
+ (write-lisp-info "info.dat")
+ (run-compare "signal-slot" #'signal-slot
+ #'cl-smoke-benchmark-signal-slot 1000 1000)
+ (run-compare "inline-call" #'inline-call
+ #'cl-smoke-benchmark-byte-array-size 10000 3000)
+ (run-compare "simple-call" #'simple-call
+ #'cl-smoke-benchmark-simple-call 10000 3000)
+ (run-compare "simple-call-compile-time" #'simple-call-compile-time
+ #'cl-smoke-benchmark-simple-call 10000 1000)
+ (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 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/benchmark.sh 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+rm -- *.dat
+sbcl --eval "(require :cl-smoke.benchmark)" \
+ --eval "(cl-smoke.benchmark:run)" \
+ --eval "(quit)" || exit 1
+R --no-save < ./plot.R > /dev/null
diff -rN -u old-benchmark/construct.cpp new-benchmark/construct.cpp
--- old-benchmark/construct.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/construct.cpp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,36 @@
+#include "benchmark.h"
+
+#include <QObject>
+#include <QVector>
+
+static QVector<QObject*> a;
+
+extern "C" {
+
+CL_SMOKE_BENCHMARK_EXPORT void
+cl_smoke_benchmark_construct_setup(size_t iterations)
+{
+ a.resize(iterations);
+}
+
+CL_SMOKE_BENCHMARK_EXPORT char
+cl_smoke_benchmark_construct(size_t iterations)
+{
+ Q_ASSERT(a.size() == iterations);
+
+ for (size_t i=0; i<iterations; i++)
+ a[i] = new QObject();
+}
+
+CL_SMOKE_BENCHMARK_EXPORT void
+cl_smoke_benchmark_construct_cleanup(size_t iterations)
+{
+ Q_ASSERT(a.size() == iterations);
+
+ for (size_t i=0; i<iterations; i++)
+ delete a[i];
+
+ a.clear();
+}
+
+}
diff -rN -u old-benchmark/cxx.lisp new-benchmark/cxx.lisp
--- old-benchmark/cxx.lisp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/cxx.lisp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,44 @@
+(in-package :cl-smoke.benchmark)
+
+(define-foreign-library libcl-smoke-benchmark
+ (t (:default "libcl-smoke-benchmark")))
+
+(let ((*foreign-library-directories*
+ (cons (asdf:component-pathname (asdf:find-system :cl-smoke.benchmark))
+ *foreign-library-directories*)))
+ (use-foreign-library libcl-smoke-benchmark))
+
+(defctype size-t :unsigned-int)
+
+(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))
+
+(defcfun cl-smoke-benchmark-construct-cleanup :void
+ (iterations size-t))
+
+
+(defmacro with-benchmark-cxx-construct ((iterations) &body body)
+ `(progn
+ (cl-smoke-benchmark-construct-setup ,iterations)
+ ,@body
+ (cl-smoke-benchmark-construct-cleanup ,iterations)))
+
+
+(defcfun cl-smoke-benchmark-simple-call :void
+ (iterations size-t))
diff -rN -u old-benchmark/lisp-benchmark.lisp new-benchmark/lisp-benchmark.lisp
--- old-benchmark/lisp-benchmark.lisp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/lisp-benchmark.lisp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,51 @@
+(in-package :cl-smoke.benchmark)
+
+(let ((array (make-instance 'qt:byte-array :args '("foobar"))))
+ (defun inline-call (iterations)
+ (declare (fixnum iterations)
+ (optimize (speed 3)))
+ (let ((char #\Null))
+ (declare (character char))
+ (dotimes (i iterations char)
+ (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)))
+ (dotimes (i iterations)
+ (cxx:kill-timer object 0))))
+
+#+sbcl
+(smoke::define-resolve-at-compile-time cxx:kill-timer)
+
+(let ((object (make-instance 'qt:object)))
+ (declare (qt:object object))
+ (defun simple-call-compile-time (iterations)
+ (declare (fixnum iterations)
+ (optimize (speed 3)))
+ (dotimes (i iterations)
+ (cxx:kill-timer object 0))))
+
+(defclass my-object (qt:object)
+ ()
+ (:metaclass cxx:class))
+
+
+(defun signal-slot (iterations)
+ (declare (fixnum iterations)
+ (optimize (speed 3)))
+ (let ((my-signal (make-instance 'cl-smoke.qt.core::qsignal :argument-types nil)))
+ (declare (function my-signal))
+ (qt:connect my-signal
+ #'(lambda ()))
+ (dotimes (i iterations)
+ (funcall my-signal))))
+
+
+(defun construct (iterations)
+ (declare (fixnum iterations)
+ (optimize (speed 3)))
+ (dotimes (i iterations)
+ (make-instance 'qt:object)))
diff -rN -u old-benchmark/overload.cpp new-benchmark/overload.cpp
--- old-benchmark/overload.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/overload.cpp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,29 @@
+#include "benchmark.h"
+
+#include <QObject>
+#include <QMetaObject>
+
+class my_object : public QObject
+{
+ public:
+ virtual const QMetaObject*
+ metaObject() const
+ { return NULL; }
+};
+
+extern "C" {
+
+CL_SMOKE_BENCHMARK_EXPORT unsigned
+cl_smoke_benchmark_overload(size_t iterations)
+{
+ my_object object;
+ QObject& o = object;
+ unsigned m = 0;
+
+ for (size_t i=0; i<iterations; i++)
+ m += reinterpret_cast<unsigned>(o.metaObject());
+
+ return m;
+}
+
+} // extern "C"
diff -rN -u old-benchmark/package.lisp new-benchmark/package.lisp
--- old-benchmark/package.lisp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/package.lisp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,3 @@
+(defpackage :cl-smoke.benchmark
+ (:use :cl :cxx-support :cffi)
+ (:export #:run))
diff -rN -u old-benchmark/plot.R new-benchmark/plot.R
--- old-benchmark/plot.R 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/plot.R 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +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)
+ 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", 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",
+ 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_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:22.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<iterations; i++)
+ object.emit_my_signal();
+}
+
+} // extern "C"
diff -rN -u old-benchmark/signal_slot.h new-benchmark/signal_slot.h
--- old-benchmark/signal_slot.h 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/signal_slot.h 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,23 @@
+#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
diff -rN -u old-benchmark/simple-call.cpp new-benchmark/simple-call.cpp
--- old-benchmark/simple-call.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new-benchmark/simple-call.cpp 2014-10-30 07:07:22.000000000 +0100
@@ -0,0 +1,16 @@
+#include "benchmark.h"
+
+#include <QObject>
+
+static QObject object;
+
+extern "C" {
+
+CL_SMOKE_BENCHMARK_EXPORT void
+cl_smoke_benchmark_simple_call(size_t iterations)
+{
+ for (size_t i=0; i<iterations; i++)
+ object.killTimer(0);
+}
+
+} // extern "C"