Skip to content

Commit

Permalink
Add first micro-benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
erikd committed Aug 31, 2015
1 parent e48ca8d commit 95fc3bf
Show file tree
Hide file tree
Showing 7 changed files with 336 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -74,3 +74,4 @@ test/metaflac.flac
test/picture.diff
test/picture.log
.dirstamp
microbench/benchmark_residual
2 changes: 1 addition & 1 deletion Makefile.am
Expand Up @@ -31,7 +31,7 @@

ACLOCAL_AMFLAGS = -I m4

SUBDIRS = doc include m4 man src examples test build objs
SUBDIRS = doc include m4 man src examples test build objs microbench

EXTRA_DIST = \
COPYING.FDL \
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -492,6 +492,7 @@ AC_CONFIG_FILES([ \
objs/release/Makefile \
objs/release/bin/Makefile \
objs/release/lib/Makefile \
microbench/Makefile
])
AC_OUTPUT

Expand Down
37 changes: 37 additions & 0 deletions microbench/Makefile.am
@@ -0,0 +1,37 @@
# FLAC - Free Lossless Audio Codec
# Copyright (C) 2015 Xiph.Org Foundation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of the Xiph.org Foundation nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/libFLAC/include

noinst_PROGRAMS = benchmark_residual


benchmark_residual_SOURCES = benchmark_residual.c util.c
151 changes: 151 additions & 0 deletions microbench/benchmark_residual.c
@@ -0,0 +1,151 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2014 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <math.h>
#include <string.h>
#include "FLAC/ordinals.h"
#include "share/compat.h"
#include "private/bitmath.h"
#include "private/fixed.h"
#include "private/macros.h"
#include "FLAC/assert.h"

#include "util.h"

static void FLAC__fixed_compute_residual_shift(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[])
{
const int idata_len = (int) data_len;
int i;

switch(order) {
case 0:
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
memcpy(residual, data, sizeof(residual[0])*data_len);
break;
case 1:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - data[i-1];
break;
case 2:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - (data[i-1] << 1) + data[i-2];
break;
case 3:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3];
break;
case 4:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4];
break;
default:
FLAC__ASSERT(0);
}
}

static void FLAC__fixed_compute_residual_mult(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[])
{
const int idata_len = (int)data_len;
int i;

switch(order) {
case 0:
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
memcpy(residual, data, sizeof(residual[0])*data_len);
break;
case 1:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - data[i-1];
break;
case 2:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - 2*data[i-1] + data[i-2];
break;
case 3:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3];
break;
case 4:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4];
break;
default:
FLAC__ASSERT(0);
}
}

static FLAC__int32 data [200000] ;
static FLAC__int32 residual [200000] ;

static unsigned bench_order = 0 ;

static void
bench_shift (void)
{ FLAC__fixed_compute_residual_shift (data, ARRAY_LEN (data), bench_order, residual) ;
}

static void
bench_mult (void)
{ FLAC__fixed_compute_residual_mult (data, ARRAY_LEN (data), bench_order, residual) ;
}

int
main (void)
{ bench_stats stats ;

puts ("") ;

for (bench_order = 2 ; bench_order <= 4 ; bench_order ++) {
memset (&stats, 0, sizeof (stats)) ;
stats.testfunc = bench_shift ;
stats.run_count = 100 ;
stats.loop_count = 10 ;

benchmark_stats (&stats) ;
printf ("shift order %u : %f %f %f %f\n", bench_order, stats.min_time, stats.median_time, stats.mean_time, stats.max_time) ;

memset (&stats, 0, sizeof (stats)) ;
stats.testfunc = bench_mult ;
stats.run_count = 100 ;
stats.loop_count = 10 ;

benchmark_stats (&stats) ;
printf ("mult order %u : %f %f %f %f\n\n", bench_order, stats.min_time, stats.median_time, stats.mean_time, stats.max_time) ;
}

return 0 ;
}
102 changes: 102 additions & 0 deletions microbench/util.c
@@ -0,0 +1,102 @@
/* FLAC - Free Lossless Audio Codec
* Copyright (C) 2015 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#define _GNU_SOURCE

#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

#include "util.h"

static double
timespec_diff (const struct timespec * start, const struct timespec * end)
{ struct timespec difftime;

if (end->tv_nsec - start->tv_nsec < 0)
{ difftime.tv_sec = end->tv_sec - start->tv_sec - 1 ;
difftime.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec ;
}
else
{ difftime.tv_sec = end->tv_sec - start->tv_sec ;
difftime.tv_nsec = end->tv_nsec-start->tv_nsec ;
} ;

return difftime.tv_sec + 1e-9 * difftime.tv_nsec ;
}

double
benchmark_function (void (*testfunc) (void), unsigned count)
{ struct timespec start, end;
unsigned k ;

clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start) ;

for (k = 0 ; k < count ; k++)
testfunc () ;

clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end) ;

return timespec_diff (&start, &end) / count ;
} /* benchmark_function */

static int
double_cmp (const void * a, const void * b)
{ const double * pa = (double *) a ;
const double * pb = (double *) b ;
return pa [0] < pb [0] ;
} /* double_cmp */

void
benchmark_stats (bench_stats * stats)
{ double sum, times [stats->run_count] ;
unsigned k ;

for (k = 0 ; k < stats->run_count ; k++)
times [k] = benchmark_function (stats->testfunc, stats->loop_count) ;

qsort (times, stats->run_count, sizeof (times [0]), double_cmp) ;

sum = 0.0 ;
stats->min_time = stats->max_time = times [0] ;
for (k = 0 ; k < stats->run_count ; k++)
{ stats->min_time = stats->min_time < times [k] ? stats->min_time : times [k] ;
stats->max_time = stats->max_time > times [k] ? stats->max_time : times [k] ;
sum += times [k] ;
}
stats->mean_time = sum / stats->run_count ;
if (stats->run_count & 1)
stats->median_time = times [(stats->run_count + 1) / 2] ;
else
stats->median_time = 0.5 * (times [stats->run_count / 2] + times [(stats->run_count / 2) + 1]) ;

return ;
} /* benchmark_stats */
43 changes: 43 additions & 0 deletions microbench/util.h
@@ -0,0 +1,43 @@
/* FLAC - Free Lossless Audio Codec
* Copyright (C) 2015 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#define ARRAY_LEN(x) ((sizeof (x) / sizeof (x [0])))

typedef struct bench_stats
{ void (*testfunc) (void) ;
unsigned run_count ;
unsigned loop_count ;
double min_time, mean_time, median_time, max_time ;
} bench_stats ;

double benchmark_function (void (*testfunc) (void), unsigned count) ;

void benchmark_stats (bench_stats * stats) ;

0 comments on commit 95fc3bf

Please sign in to comment.