diff options
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | debian/changelog | 14 | ||||
-rw-r--r-- | debian/compat | 1 | ||||
-rw-r--r-- | debian/control | 16 | ||||
-rw-r--r-- | debian/copyright | 28 | ||||
-rw-r--r-- | debian/dirs | 1 | ||||
-rwxr-xr-x | debian/rules | 90 | ||||
-rw-r--r-- | mbw.1 | 55 | ||||
-rw-r--r-- | mbw.c | 275 | ||||
-rw-r--r-- | mbw.spec | 43 |
10 files changed, 535 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be6852c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +#CFLAGS=-O2 -Wall -g +NAME=mbw + +mbw: mbw.c + +clean: + rm -f mbw + rm -f ${NAME}.tar.gz + +rpm: clean + tar cCzf .. ${NAME}.tar.gz ${NAME} + rpmbuild -ta ${NAME}.tar.gz diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..060f732 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,14 @@ +mbw (1.1.1-2) unstable; urgency=low + + [ Emmanuel QUEMENER ] + * Modify manual page syntax error. + * Modify rules to remove deprecated reference option on dh_clean. + + -- Emmanuel QUEMENER <emmanuel.quemener@free.fr> Wed, 04 Nov 2009 07:41:56 +0100 + +mbw (1.1.1-1) unstable; urgency=low + + * Initial release (Closes: bug#510680). + + -- Emmanuel QUEMENER <emmanuel.quemener@free.fr> Thu, 01 Jan 2009 22:15:04 +0100 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..598dcb0 --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: mbw +Section: utils +Priority: extra +Maintainer: Emmanuel QUEMENER <emmanuel.quemener@free.fr> +Build-Depends: debhelper (>= 7) +Standards-Version: 3.8.0 +Homepage: http://ahorvath.web.cern.ch/ahorvath/mbw/ + +Package: mbw +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: memory bandwidth benchmark program + MBW determines the "copy" memory bandwidth available to userspace programs. + Its simplistic approach models that of real applications. + It is not tuned to extremes and it is not aware of hardware architecture, + just like your average software package. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f40c8e3 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,28 @@ +This package was debianized by Emmanuel QUEMENER <emmanuel.quemener@free.fr> on +Thu, 01 Jan 2009 22:15:04 +0100. + +It was downloaded from http://ahorvath.web.cern.ch/ahorvath/mbw/ + + Copyright (C) 2008 Andras Horvath <Andras.Horvath@cern.ch> + +License: + +Permission to use and copy is granted subject to the terms of the +"GNU Lesser General Public License" (LGPL) as published by the +Free Software Foundation; either version 2.1 of the License, +or any later version. In addition, Julius O. Smith III requests +that a copy of any modified files be sent by email to +jos@ccrma.stanford.edu so that he may incorporate them into the +CCRMA version. + + This 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. + +On Debian systems, the text of the GPL is available in the file: +/usr/share/common-licenses/LGPL + +The Debian packaging is (C) 2009, Emmanuel QUEMENER <emmanuel.quemener@free.fr> +and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +usr/bin diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..4b638c1 --- /dev/null +++ b/debian/rules @@ -0,0 +1,90 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + + +build: build-stamp + +build-stamp: + dh_testdir + + # Add here commands to compile the package. + CFLAGS="$(CFLAGS)" $(MAKE) + #docbook-to-man debian/mbw.sgml > mbw.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + $(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + #dh_clean -k + dh_prep + dh_installdirs + + # Add here commands to install the package into debian/mbw. + # $(MAKE) DESTDIR=$(CURDIR)/debian/mbw install + cp mbw $(CURDIR)/debian/mbw/usr/bin + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman mbw.1 + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure @@ -0,0 +1,55 @@ +.TH mbw 1 "Apr 26, 2006" "memory bandwidth benchmark" + +.SH NAME +mbw \- Memory BandWidth benchmark + +.SH SYNOPSIS +.B mbw +.RI [options]\ arraysize_in_MiB +.br + +.SH DESCRIPTION +.B mbw +determines available memory bandwidth by copying large arrays of data in memory. + +.SH OPTIONS +.B +.IP -q +Quiet; suppress informational messages. +.B +.IP -a +Suppress printing the average of each test. +.B +.IP "\-n <number>" +Select number of loops per test +.B +.IP "\-t <number>" +Select tests to be run. If no -t parameters are given the default is to run all tests. -t0: memcpy() test, -t1: dumb (b[i]=a[i] style) test, -t2: memcpy() with arbitrary block size +.B +.IP "\-b <bytes>" +Block size in bytes for -t2. +.B +.IP -h +Show quick help. + +.SH USAGE +.B mbw +will allocate two +.B arraysize +arrays in memory and copy one to the other. +Reported 'bandwidth' is the amount of data copied over the time this operation took. + +Obviously +.B mbw +needs twice +.B arraysize +MiBytes (1024*1024 bytes) of physical memory \- you'd better switch off swap or +otherwise make sure no paging occurs. Needless to say that it should not be run +on a busy system. + +.SH TODO +Multiple thread support. +Better configurability, including using getopt() for parsing arguments. + +.SH AUTHOR +Andras.Horvath@cern.ch @@ -0,0 +1,275 @@ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> +#include <string.h> +#include <unistd.h> + +/* how many runs to average by default */ +#define DEFAULT_NR_LOOPS 10 + +/* we have 3 tests at the moment */ +#define MAX_TESTS 3 + +/* default block size for test 2, in bytes */ +#define DEFAULT_BLOCK_SIZE 262144 + +/* + * Bare-bones memory bandwidth tester + * + * Andras.Horvath@cern.ch + * compile with: + * gcc -O -o mbw mbw.c + * + * run with eg.: + * + * ./mbw 300 + * + * or './mbw -h' for help + * + * watch out for swap usage (or turn off swap) + */ + +void usage() { + printf("Usage: mbw [options] array_size_in_MiB\n"); + printf("Options:\n"); + printf(" -n: number of runs per test\n"); + printf(" -a: Don't display average\n"); + printf(" -t0: memcpy test\n"); + printf(" -t1: dumb (b[i]=a[i] style) test\n"); + printf(" -t2 : memcpy test with fixed block size\n"); + printf(" -b <size>: block size in bytes for -t2 (default: %d)\n",DEFAULT_BLOCK_SIZE); + printf(" -q: quiet (print statistics only)\n"); + printf("(will then use two arrays, watch out for swapping)\n"); + printf("'Bandwidth' is amount of data copied over the time this operation took.\n"); + printf("\nThe default is to run all tests available.\n"); +} + +/* ------------------------------------------------------ */ + +/* allocate a test array and fill it with data + * so as to force Linux to _really_ allocate it */ +long *make_array(unsigned long long asize) { + unsigned long long t; + unsigned int long_size=sizeof(long); + long *a; + + a=calloc(asize, long_size); + + if(NULL==a) { + perror("Error allocating memory"); + exit(1); + } + + /* make sure both arrays are allocated, fill with pattern */ + for(t=0; t<asize; t++) { + a[t]=0xaa; + } + return a; +} + +/* actual benchmark */ +/* asize: number of type 'long' elements in test arrays + * long_size: sizeof(long) cached + * type: 0=use memcpy, 1=use dumb copy loop (whatever GCC thinks best) + * + * return value: elapsed time in seconds + */ +double worker(unsigned long long asize, long *a, long *b, int type, unsigned long long block_size) { + unsigned long long t; + struct timeval starttime,endtime; + double te; + unsigned int long_size=sizeof(long); + long *c; /* where are we in test=2? */ + /* array size in bytes */ + unsigned long long array_bytes=asize*long_size; + + if(type==1) { /* memcpy test */ + /* timer starts */ + gettimeofday(&starttime, NULL); + memcpy(b,a,array_bytes); + /* timer stops */ + gettimeofday(&endtime, NULL); + } else if(type==2) { /* memcpy block test */ + gettimeofday(&starttime, NULL); + for(t=0; t<array_bytes; t+=block_size) { + c=mempcpy(b,a,block_size); + } + if(t>array_bytes){ + c=mempcpy(b,a,t-array_bytes); + } + gettimeofday(&endtime, NULL); + } else { /* dumb test */ + gettimeofday(&starttime, NULL); + for(t=0; t<asize; t++) { + b[t]=a[t]; + } + gettimeofday(&endtime, NULL); + } + + te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000; + + return te; +} + +/* ------------------------------------------------------ */ + +/* pretty print worker's output in human-readable terms */ +/* te: elapsed time in seconds + * mt: amount of transferred data in MiB + * type: see 'worker' above + * + * return value: - + */ +void printout(double te, double mt, int type) { + switch(type) { + case 0: + printf("Method: MEMCPY\t"); + break; + case 1: printf("Method: DUMB\t"); + break; + case 2: printf("Method: MCBLOCK\t"); + break; + } + printf("Elapsed: %.5f\t",te); + printf("MiB: %.5f\t",mt); + printf("Copy: %.3f MiB/s\n", mt/te); + return; +} + +/* ------------------------------------------------------ */ + +int main(int argc, char **argv) { + unsigned int long_size=0; + double te,te_sum; /* time elapsed */ + unsigned long long asize=0; /* array size (elements in array) */ + int i; + long *a, *b; /* the two arrays to be copied from/to */ + int o; /* getopt options */ + unsigned long testno; + + /* options */ + int nr_loops=DEFAULT_NR_LOOPS; /* how many runs to average? */ + unsigned long long block_size=DEFAULT_BLOCK_SIZE; /* fixed memcpy block size for -t2 */ + int showavg=1; /* show average, -a */ + /* what tests to run (-t x) */ + int tests[MAX_TESTS]; + double mt=0; /* MiBytes transferred == array size in MiB */ + int quiet=0; /* suppress extra messages */ + + tests[0]=0; + tests[1]=0; + tests[2]=0; + + while((o=getopt(argc, argv, "haqn:t:b:")) != EOF) { + switch(o) { + case 'h': + usage(); + exit(1); + break; + case 'a': /* suppress printing average */ + showavg=0; + break; + case 'n': /* no. loops */ + nr_loops=strtoul(optarg, (char **)NULL, 10); + break; + case 't': /* test to run */ + testno=strtoul(optarg, (char **)NULL, 10); + if(0>testno) { + printf("Error: test number must be between 0 and %d\n",MAX_TESTS); + usage(); + exit(1); + } + tests[testno]=1; + break; + case 'b': /* block size in bytes*/ + block_size=strtoull(optarg, (char **)NULL, 10); + if(0>=block_size) { + printf("Error: what block size do you mean?\n"); + usage(); + exit(1); + } + break; + case 'q': /* quiet */ + quiet=1; + break; + default: + break; + } + } + + /* default is to run all tests if no specific tests were requested */ + if( (tests[0]+tests[1]+tests[2]) == 0) { + tests[0]=1; + tests[1]=1; + tests[2]=1; + } + + if(optind<argc) { + mt=strtoul(argv[optind++], (char **)NULL, 10); + } else { + printf("Error: no array size given!\n"); + usage(); + exit(1); + } + + if(0>=mt) { + printf("Error: array size wrong!\n"); + usage(); + exit(1); + } + + /* ------------------------------------------------------ */ + + long_size=sizeof(long); /* the size of long on this platform */ + asize=1024*1024/long_size*mt; /* how many longs then in one array? */ + + if(asize*long_size < block_size) { + printf("Error: array size larger than block size!\n"); + usage(); + exit(1); + } + + if(!quiet) { + printf("Long uses %d bytes. ",long_size); + printf("Allocating 2*%lld elements = %lld bytes of memory.\n",asize,2*asize*long_size); + if(tests[2]) { + printf("Using %lld bytes as blocks for memcpy block copy test.\n",block_size); + } + } + + a=make_array(asize); + b=make_array(asize); + + /* ------------------------------------------------------ */ + if(!quiet) { + printf("Getting down to business... Doing %d runs per test.\n",nr_loops); + } + + /* run all tests requested, the proper number of times */ + for(testno=0; testno<MAX_TESTS; testno++) { + te_sum=0; + if(tests[testno]) { + for (i=0; i<nr_loops; i++) { + te=worker(asize,a,b,testno,block_size); + te_sum+=te; + printf("%d\t",i); + printout(te,mt,testno); + } + if(showavg) { + printf("AVG\t"); + printout(te_sum/nr_loops,mt,testno); + } + } + } + + free(a); + free(b); + return 0; +} diff --git a/mbw.spec b/mbw.spec new file mode 100644 index 0000000..769b796 --- /dev/null +++ b/mbw.spec @@ -0,0 +1,43 @@ +Summary: Memory bandwidth benchmark +Name: mbw +Version: 1.1 +Release: 1 +License: LGPL +Buildroot: %{_tmppath}/%{name}-buildroot +Group: System Environment/Base +Source: %{name}.tar.gz +Packager: Andras.Horvath@cern.ch + +%description +Test memory copy bandwidth (single thread). Switch off swap or make sure array size does not exceed available free RAM. + +%prep +%setup -n %{name} + +%build +make + +%install +mkdir -p %{buildroot}/usr/bin +mkdir -p %{buildroot}%{_mandir}/man1 +install -m 755 -o root -g root mbw %{buildroot}/usr/bin/mbw +install -m 644 -o root -g root mbw.1 %{buildroot}%{_mandir}/man1/mbw.1 + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +/usr/bin/mbw +%doc +%{_mandir}/man1/mbw.1.gz + +%changelog +* Tue Jul 07 2006 Andras Horvath <Andras.Horvath@cern.ch> 1.1-1 +- separate array initialization from work -> faster execution +- getopt() options parsing: suppress average, specific tests only, no. runs +- added quiet mode +- added a new test: memcpy() with given block size + +* Thu Apr 26 2006 Andras Horvath <Andras.Horvath@cern.ch> 1.0-1 +- initial release |