From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <libc-alpha-return-53388-listarch-libc-alpha=sources.redhat.com@sourceware.org> Received: (qmail 13772 invoked by alias); 7 Oct 2014 15:54:59 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: <libc-alpha.sourceware.org> List-Subscribe: <mailto:libc-alpha-subscribe@sourceware.org> List-Archive: <http://sourceware.org/ml/libc-alpha/> List-Post: <mailto:libc-alpha@sourceware.org> List-Help: <mailto:libc-alpha-help@sourceware.org>, <http://sourceware.org/ml/#faqs> Sender: libc-alpha-owner@sourceware.org Received: (qmail 13762 invoked by uid 89); 7 Oct 2014 15:54:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.7 required=5.0 tests=AWL,BAYES_05,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Date: Tue, 07 Oct 2014 15:54:00 -0000 From: Siddhesh Poyarekar <siddhesh@redhat.com> To: Will Newton <will.newton@linaro.org> Cc: libc-alpha@sourceware.org Subject: Re: [PATCH 1/3] benchtests: Add malloc microbenchmark Message-ID: <20141007155447.GH30688@spoyarek.pnq.redhat.com> References: <1412349086-11473-1-git-send-email-will.newton@linaro.org> <1412349086-11473-2-git-send-email-will.newton@linaro.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="wayzTnRSUXKNfBqd" Content-Disposition: inline In-Reply-To: <1412349086-11473-2-git-send-email-will.newton@linaro.org> User-Agent: Mutt/1.5.22.1-rc1 (2013-10-16) X-SW-Source: 2014-10/txt/msg00186.txt.bz2 --wayzTnRSUXKNfBqd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-length: 7539 On Fri, Oct 03, 2014 at 04:11:24PM +0100, Will Newton wrote: > Add a microbenchmark for measuring malloc and free performance. The > benchmark allocates and frees buffers of random sizes in a random order > and measures the overall execution time and RSS. >=20 > The random block sizes used follow an inverse square distribution > which is intended to mimic the behaviour of real applications which > tend to allocate many more small blocks than large ones. >=20 > ChangeLog: >=20 > 2014-10-03 Will Newton <will.newton@linaro.org> >=20 > * benchtests/Makefile (stdlib-bench): Add malloc benchmark. > * benchtests/bench-malloc.c: New file. Looks OK to me with one minor nit (pointed out below) fixed. > --- > benchtests/Makefile | 2 +- > benchtests/bench-malloc.c | 219 ++++++++++++++++++++++++++++++++++++++++= ++++++ > 2 files changed, 220 insertions(+), 1 deletion(-) > create mode 100644 benchtests/bench-malloc.c >=20 > diff --git a/benchtests/Makefile b/benchtests/Makefile > index fd3036d..1f8eb82 100644 > --- a/benchtests/Makefile > +++ b/benchtests/Makefile > @@ -37,7 +37,7 @@ string-bench :=3D bcopy bzero memccpy memchr memcmp mem= cpy memmem memmove \ > strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok > string-bench-all :=3D $(string-bench) >=20=20 > -stdlib-bench :=3D strtod > +stdlib-bench :=3D strtod malloc >=20=20 > benchset :=3D $(string-bench-all) $(stdlib-bench) >=20=20 > diff --git a/benchtests/bench-malloc.c b/benchtests/bench-malloc.c > new file mode 100644 > index 0000000..54631ed > --- /dev/null > +++ b/benchtests/bench-malloc.c > @@ -0,0 +1,219 @@ > +/* Benchmark malloc and free functions. > + Copyright (C) 2013-2014 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <math.h> > +#include <signal.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/time.h> > +#include <sys/resource.h> > +#include <unistd.h> > + > +#include "bench-timing.h" > +#include "json-lib.h" > + > +/* Benchmark duration in seconds. */ > +#define BENCHMARK_DURATION 60 > +#define RAND_SEED 88 > + > +/* Maximum memory that can be allocated at any one time is: > + > + WORKING_SET_SIZE * MAX_ALLOCATION_SIZE > + > + However due to the distribution of the random block sizes > + the typical amount allocated will be much smaller. */ > +#define WORKING_SET_SIZE 1024 > + > +#define MIN_ALLOCATION_SIZE 4 > +#define MAX_ALLOCATION_SIZE 32768 > + > +/* Get a random block size with an inverse square distribution. */ > +static unsigned int > +get_block_size (unsigned int rand_data) > +{ > + /* Inverse square. */ > + const float exponent =3D -2; > + /* Minimum value of distribution. */ > + const float dist_min =3D MIN_ALLOCATION_SIZE; > + /* Maximum value of distribution. */ > + const float dist_max =3D MAX_ALLOCATION_SIZE; > + > + float min_pow =3D powf (dist_min, exponent + 1); > + float max_pow =3D powf (dist_max, exponent + 1); > + > + float r =3D (float) rand_data / RAND_MAX; > + > + return (unsigned int) powf ((max_pow - min_pow) * r + min_pow, 1 / (ex= ponent + 1)); > +} > + > +#define NUM_BLOCK_SIZES 8000 > +#define NUM_OFFSETS ((WORKING_SET_SIZE) * 4) > + > +static unsigned int random_block_sizes[NUM_BLOCK_SIZES]; > +static unsigned int random_offsets[NUM_OFFSETS]; > + > +static void > +init_random_values (void) > +{ > + for (size_t i =3D 0; i < NUM_BLOCK_SIZES; i++) > + random_block_sizes[i] =3D get_block_size (rand ()); > + > + for (size_t i =3D 0; i < NUM_OFFSETS; i++) > + random_offsets[i] =3D rand () % WORKING_SET_SIZE; > +} > + > +static unsigned int > +get_random_block_size (unsigned int *state) > +{ > + unsigned int idx =3D *state; > + > + if (idx >=3D NUM_BLOCK_SIZES - 1) > + idx =3D 0; > + else > + idx++; > + > + *state =3D idx; > + > + return random_block_sizes[idx]; > +} > + > +static unsigned int > +get_random_offset (unsigned int *state) > +{ > + unsigned int idx =3D *state; > + > + if (idx >=3D NUM_OFFSETS - 1) > + idx =3D 0; > + else > + idx++; > + > + *state =3D idx; > + > + return random_offsets[idx]; > +} > + > +static volatile bool timeout; > + > +static void alarm_handler (int signum) Line break after void. > +{ > + timeout =3D true; > +} > + > +/* Allocate and free blocks in a random order. */ > +static size_t > +malloc_benchmark_loop (void **ptr_arr) > +{ > + unsigned int offset_state =3D 0, block_state =3D 0; > + size_t iters =3D 0; > + > + while (!timeout) > + { > + unsigned int next_idx =3D get_random_offset (&offset_state); > + unsigned int next_block =3D get_random_block_size (&block_state); > + > + free (ptr_arr[next_idx]); > + > + ptr_arr[next_idx] =3D malloc (next_block); > + > + iters++; > + } > + > + return iters; > +} > + > +static timing_t > +do_benchmark (size_t *iters) > +{ > + timing_t elapsed, start, stop; > + void *working_set[WORKING_SET_SIZE]; > + > + memset (working_set, 0, sizeof (working_set)); > + > + TIMING_NOW (start); > + *iters =3D malloc_benchmark_loop (working_set); > + TIMING_NOW (stop); > + > + TIMING_DIFF (elapsed, start, stop); > + > + return elapsed; > +} > + > +int > +main (int argc, char **argv) > +{ > + timing_t cur; > + size_t iters =3D 0; > + unsigned long res; > + json_ctx_t json_ctx; > + double d_total_s, d_total_i; > + struct sigaction act; > + > + init_random_values (); > + > + json_init (&json_ctx, 0, stdout); > + > + json_document_begin (&json_ctx); > + > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > + > + json_attr_object_begin (&json_ctx, "functions"); > + > + json_attr_object_begin (&json_ctx, "malloc"); > + > + json_attr_object_begin (&json_ctx, ""); > + > + TIMING_INIT (res); > + > + (void) res; > + > + memset (&act, 0, sizeof (act)); > + act.sa_handler =3D &alarm_handler; > + > + sigaction (SIGALRM, &act, NULL); > + > + alarm (BENCHMARK_DURATION); > + > + cur =3D do_benchmark (&iters); > + > + struct rusage usage; > + getrusage(RUSAGE_SELF, &usage); > + > + d_total_s =3D cur; > + d_total_i =3D iters; > + > + json_attr_double (&json_ctx, "duration", d_total_s); > + json_attr_double (&json_ctx, "iterations", d_total_i); > + json_attr_double (&json_ctx, "time_per_iteration", d_total_s / d_total= _i); > + json_attr_double (&json_ctx, "max_rss", usage.ru_maxrss); > + > + json_attr_double (&json_ctx, "min_size", MIN_ALLOCATION_SIZE); > + json_attr_double (&json_ctx, "max_size", MAX_ALLOCATION_SIZE); > + json_attr_double (&json_ctx, "random_seed", RAND_SEED); > + > + json_attr_object_end (&json_ctx); > + > + json_attr_object_end (&json_ctx); > + > + json_attr_object_end (&json_ctx); > + > + json_document_end (&json_ctx); > + > + return 0; > +} > --=20 > 1.9.3 >=20 --wayzTnRSUXKNfBqd Content-Type: application/pgp-signature Content-length: 473 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJUNAzHAAoJEHnEPfvxzyGHOE4H/R47ITpzJHjPQvsn9fazfVGU 7P05ovcuiEHeZe8LCvzsemIyVEtzZcBdJTDgL6zER4FEy6tXDdfLHDWMWz2QQGOe ZaecgJhuVy0vh+urnOypJL0znLjnJlJSl6I1lF9YH9ryplszJ6+dpp9y1aaghI/m VHyhqxCCtuzRExYSUEvyNu2jEabIrcVQVinSRCoLW5PtG/oeel/Y0YvEFqkDIx76 Js4yWgqcLO3pJLwMSEiQ4E4G/uBgXu+6sTRpEreCQMU37kJ1zm2u9csMsVVzLsR7 B6i+XBUUcUL6XbUHDqDFZOjTb5Sut8K3wCKA1rvHbGRh/Kgn8QxXsRVztYY8fJ0= =ZTcn -----END PGP SIGNATURE----- --wayzTnRSUXKNfBqd--