From 93787830f595028f6fb780ca19abff79638cfa6f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Nov 2016 14:04:29 +0100 Subject: [PATCH 1/3] testbench: add performance-testing tools closes https://github.com/rsyslog/libfastjson/issues/129 --- .travis.yml | 3 +++ tests/Makefile.am | 9 ++++++- tests/perf_to_string.c | 51 +++++++++++++++++++++++++++++++++++++++ tests/perf_to_string.test | 32 ++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/perf_to_string.c create mode 100755 tests/perf_to_string.test diff --git a/.travis.yml b/.travis.yml index a627507..8e12ee7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ install: - sh autogen.sh before_script: + - sudo apt-get -qq --force-yes install valgrind - # note: valgrind is only available on Linux - if [ "$CC" == "gcc" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export ENA_VG="--enable-valgrind"; fi - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export SANITIZER="-fsanitize=address" ; fi @@ -38,6 +39,8 @@ before_script: script: - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then scan-build-3.6 --status-bugs make check TESTS="" && make clean ; fi - make + - valgrind --tool=callgrind ls - export VERBOSE=1 - make check + - cat tests/perf_to_string.trs - make distcheck diff --git a/tests/Makefile.am b/tests/Makefile.am index 9dca5da..231cc06 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -32,7 +32,8 @@ check_PROGRAMS += $(TESTS:.test=) # some programs that do internal checking check_PROGRAMS += chk_version \ - cr_obj_multi + cr_obj_multi \ + perf_to_string TESTS += chk_version @@ -60,6 +61,12 @@ check_PROGRAMS += test_object_object_add_exFormatted test_object_object_add_exFormatted_SOURCES = test_object_object_add_ex.c parse_flags.c parse_flags.h test_object_object_add_exFormatted_CPPFLAGS = -DTEST_FORMATTED +# performancebaseline tests +# TODO: guard via configure switch! -- rgerhards, 2016-11-29 +TESTS += perf_to_string.test + + + EXTRA_DIST= EXTRA_DIST += $(TESTS) EXTRA_DIST += test-defs.sh diff --git a/tests/perf_to_string.c b/tests/perf_to_string.c new file mode 100644 index 0000000..5e05a43 --- /dev/null +++ b/tests/perf_to_string.c @@ -0,0 +1,51 @@ +/* libfastjson testbench tool + * This program can be used to test the performance of the _to_string() + * subsystem. It is meant to be used together with a profiler. + * + * Copyright (c) 2016 Adiscon GmbH + * Rainer Gerhards + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ +#include "config.h" + +#include "../json.h" + +#include +#include +#include + +#define NUM_ITERATIONS 100000 + +int +main(int __attribute__((unused)) argc, char __attribute__((unused)) **argv) +{ + int i; + struct fjson_object *json; + + json = fjson_object_new_object(); + fjson_object_object_add(json, "string1", fjson_object_new_string("This is a test")); + fjson_object_object_add(json, "string2", fjson_object_new_string("This is a " + "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong" + "test")); + fjson_object_object_add(json, "string3", fjson_object_new_string("This is\n a test öäü")); + fjson_object_object_add(json, "int1", fjson_object_new_int(4711)); + + + for(i = 0 ; i < NUM_ITERATIONS ; ++i) { + const char *dummy = fjson_object_to_json_string(json); + if(dummy == NULL) { + fprintf(stderr, "dummy has received no output!"); + exit(1); + } + if(i == 0) + printf("%s\n", dummy); + } + + fjson_object_put(json); + return 0; +} diff --git a/tests/perf_to_string.test b/tests/perf_to_string.test new file mode 100755 index 0000000..29054c7 --- /dev/null +++ b/tests/perf_to_string.test @@ -0,0 +1,32 @@ +#!/bin/sh +# Common definitions +#if test -z "$srcdir"; then + #srcdir="${0%/*}" + #test "$srcdir" = "$0" && srcdir=. + #test -z "$srcdir" && srcdir=. +#fi +#. "$srcdir/test-defs.sh" + +# first, get baseline from system-installed library +rm -f callgrind.out &> /dev/null +valgrind --tool=callgrind --callgrind-out-file=callgrind.out .libs/perf_to_string +export RETCODE=$? +echo return code $RETCODE +MAXCYCLES=$(grep < callgrind.out "^totals:" | tr -dc '0-9') +echo "system installed libfastjson requires $MAXCYCLES cycles" +# give 5% allowence to care for exec env differences between runs +MAXCYCLES=$((MAXCYCLES * 105)) +MAXCYCLES=$((MAXCYCLES / 100)) + +ls -l ../.libs/libfastjson.so +rm -f callgrind.out &> /dev/null +LD_PRELOAD="../.libs/libfastjson.so.4" valgrind --tool=callgrind --callgrind-out-file=callgrind.out .libs/perf_to_string +CYCLES=$(grep < callgrind.out "^totals:" | tr -dc '0-9') +echo "libfastjson being testes requires $CYCLES cycles" + +if [ $CYCLES -gt $MAXCYCLES ]; then + echo + echo performance issue: we need $CYCLES cycles, but upper bound is $MAXCYCLES + exit 1 +fi +rm callgrind.out From 02edc6dc33374a303c1d04dd1397d1a2a372ff76 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Nov 2016 20:08:08 +0000 Subject: [PATCH 2/3] skip performance test if we cant get a baseline --- .travis.yml | 2 +- configure.ac | 17 +++++++++++++++++ tests/perf_to_string.test | 5 +++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8e12ee7..e5bde71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ before_script: - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export SANITIZER="-fsanitize=address" ; fi - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export CFLAGS="$CFLAGS -fsanitize=address" ; fi - ./CI/check_codestyle.sh - - ./configure $ENA_VG + - ./configure --enable-performance-testbench $ENA_VG script: - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then scan-build-3.6 --status-bugs make check TESTS="" && make clean ; fi diff --git a/configure.ac b/configure.ac index c63f8ca..8cb8b04 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,23 @@ if test "$enable_valgrind" = "yes"; then AC_DEFINE(VALGRIND, 1, [valgrind enabled]) fi +AC_ARG_ENABLE(performance_testbench, + [AS_HELP_STRING([--enable-performance-testbench],[enable running the performance testbench @<:@default=no@:>@])], + [case "${enableval}" in + yes) enable_performance_testbench="yes" ;; + no) enable_performance_testbench="no" ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-performance-testbench) ;; + esac], + [enable_performance_testbench="no"] +) +if test "$enable_performance_testbench" = "yes"; then + AC_CHECK_PROG(VALGRIND, [valgrind], [valgrind], [no]) + if test "x$VALGRIND" = "xno"; then + AC_MSG_ERROR([--enable-performance-testbench given, but valgrind is not present on system]) + fi +fi +AM_CONDITIONAL(ENABLE_PERFORMANCE_TESTBENCH, test x$enable_performance_testbench = xyes) + # Checks for programs. # Checks for libraries. diff --git a/tests/perf_to_string.test b/tests/perf_to_string.test index 29054c7..441276d 100755 --- a/tests/perf_to_string.test +++ b/tests/perf_to_string.test @@ -10,6 +10,11 @@ # first, get baseline from system-installed library rm -f callgrind.out &> /dev/null valgrind --tool=callgrind --callgrind-out-file=callgrind.out .libs/perf_to_string +if [ $? -ne 0 ]; then + echo "Error obtaining performance baseline, assuming system is not able to" + echo "support this test - skipping" + exit 77 +fi export RETCODE=$? echo return code $RETCODE MAXCYCLES=$(grep < callgrind.out "^totals:" | tr -dc '0-9') From a4d007ec1dd00f78a2b58416c37bf31bee2edf3e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 30 Nov 2016 14:25:32 +0100 Subject: [PATCH 3/3] travis: output testbench detail result --- .travis.yml | 5 ++++- configure.ac | 4 ++-- tests/Makefile.am | 9 +++++---- tests/perf_to_string.test | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5bde71..0ccaf48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,9 @@ install: - sh autogen.sh before_script: - - sudo apt-get -qq --force-yes install valgrind + - sudo add-apt-repository ppa:adiscon/v8-stable -y + - sudo apt-get update -qq + - sudo apt-get -qq --force-yes install valgrind libfastjson - # note: valgrind is only available on Linux - if [ "$CC" == "gcc" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export ENA_VG="--enable-valgrind"; fi - if [ "$CC" == "clang" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export SANITIZER="-fsanitize=address" ; fi @@ -42,5 +44,6 @@ script: - valgrind --tool=callgrind ls - export VERBOSE=1 - make check + - cat tests/test-suite.log - cat tests/perf_to_string.trs - make distcheck diff --git a/configure.ac b/configure.ac index 8cb8b04..d73f1d9 100644 --- a/configure.ac +++ b/configure.ac @@ -90,8 +90,8 @@ AC_ARG_ENABLE(performance_testbench, [enable_performance_testbench="no"] ) if test "$enable_performance_testbench" = "yes"; then - AC_CHECK_PROG(VALGRIND, [valgrind], [valgrind], [no]) - if test "x$VALGRIND" = "xno"; then + AC_CHECK_PROG(VALGRIND_CALLGRIND, [valgrind], [valgrind], [no]) + if test "x$VALGRIND_CALLGRIND" = "xno"; then AC_MSG_ERROR([--enable-performance-testbench given, but valgrind is not present on system]) fi fi diff --git a/tests/Makefile.am b/tests/Makefile.am index 231cc06..dbcd3ab 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -32,8 +32,7 @@ check_PROGRAMS += $(TESTS:.test=) # some programs that do internal checking check_PROGRAMS += chk_version \ - cr_obj_multi \ - perf_to_string + cr_obj_multi TESTS += chk_version @@ -62,9 +61,10 @@ test_object_object_add_exFormatted_SOURCES = test_object_object_add_ex.c parse_f test_object_object_add_exFormatted_CPPFLAGS = -DTEST_FORMATTED # performancebaseline tests -# TODO: guard via configure switch! -- rgerhards, 2016-11-29 +if ENABLE_PERFORMANCE_TESTBENCH +check_PROGRAMS += perf_to_string TESTS += perf_to_string.test - +endif EXTRA_DIST= @@ -97,6 +97,7 @@ EXTRA_DIST += test_object_object_add_exFormatted_pretty.expected EXTRA_DIST += test_object_object_add_exFormatted_spaced.expected EXTRA_DIST += test_many_subobj.expected EXTRA_DIST += test_obj_obj_get_ex-null.expected +EXTRA_DIST += perf_to_string.c testsubdir=testSubDir TESTS_ENVIRONMENT = top_builddir=$(top_builddir) diff --git a/tests/perf_to_string.test b/tests/perf_to_string.test index 441276d..a088ffe 100755 --- a/tests/perf_to_string.test +++ b/tests/perf_to_string.test @@ -13,6 +13,7 @@ valgrind --tool=callgrind --callgrind-out-file=callgrind.out .libs/perf_to_strin if [ $? -ne 0 ]; then echo "Error obtaining performance baseline, assuming system is not able to" echo "support this test - skipping" + rm callgrind.out exit 77 fi export RETCODE=$?