summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--debian/changelog14
-rw-r--r--debian/compat1
-rw-r--r--debian/control16
-rw-r--r--debian/copyright28
-rw-r--r--debian/dirs1
-rwxr-xr-xdebian/rules90
-rw-r--r--mbw.155
-rw-r--r--mbw.c275
-rw-r--r--mbw.spec43
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
diff --git a/mbw.1 b/mbw.1
new file mode 100644
index 0000000..33e2194
--- /dev/null
+++ b/mbw.1
@@ -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
diff --git a/mbw.c b/mbw.c
new file mode 100644
index 0000000..4481853
--- /dev/null
+++ b/mbw.c
@@ -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