2 * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #include <sys/param.h>
45 #define MAXNAMELEN 256
46 typedef unsigned int uint_t;
49 * Loop over directory sizes:
51 * touch n files in each directory
52 * stat the files round-robin
53 * readdir/unlink the files
54 * Change directory sizes by multiplication or addition.
55 * Allow control of starting & stopping sizes, name length, target directory.
56 * Print size and wallclock time (ms per file).
57 * Output can be used to make graphs (gnuplot)
61 static uint_t dirchars;
63 static uint_t firstsize;
64 static uint_t lastsize;
65 static uint_t minchars;
69 static uint_t pfxchars;
72 static void filename(int, int, char *);
73 static int hexchars(uint_t);
74 static uint_t nextsize(uint_t);
75 static double now(void);
76 static void usage(void);
79 * Maximum size allowed, this is pretty nuts.
80 * The largest one we've ever built has been about 2 million.
82 #define MAX_DIR_SIZE (16 * 1024 * 1024)
83 #define DFL_FIRST_SIZE 1
84 #define DFL_LAST_SIZE (1024 * 1024)
85 #define MAX_DIR_COUNT 1024
88 main(int argc, char **argv)
95 char name[MAXNAMELEN];
99 while ((c = getopt(argc, argv, "a:c:d:f:l:m:n:s:")) != -1) {
102 addval = (uint_t)atoi(optarg);
105 nchars = (uint_t)atoi(optarg);
111 firstsize = (uint_t)atoi(optarg);
114 lastsize = (uint_t)atoi(optarg);
117 mulval = atof(optarg);
120 ndirs = (uint_t)atoi(optarg);
123 stats = (uint_t)atoi(optarg);
131 if (!addval && !mulval)
133 else if ((addval && mulval) || mulval < 0.0) {
142 if (mkdir(dirname, 0777) < 0 && errno != EEXIST) {
146 if (chdir(dirname) < 0) {
152 firstsize = DFL_FIRST_SIZE;
153 else if (firstsize > MAX_DIR_SIZE)
154 firstsize = MAX_DIR_SIZE;
156 lastsize = DFL_LAST_SIZE;
157 else if (lastsize > MAX_DIR_SIZE)
158 lastsize = MAX_DIR_SIZE;
159 if (lastsize < firstsize)
160 lastsize = firstsize;
161 minchars = hexchars(lastsize - 1);
162 if (nchars < minchars)
164 else if (nchars >= MAXNAMELEN)
165 nchars = MAXNAMELEN - 1;
166 if (ndirs > MAX_DIR_COUNT)
167 ndirs = MAX_DIR_COUNT;
168 dirchars = hexchars(ndirs);
169 pfxchars = nchars - minchars;
171 memset(&name[dirchars + 1], 'a', pfxchars);
172 for (j = 0; j < ndirs; j++) {
173 filename(0, j, name);
174 name[dirchars] = '\0';
177 for (cursize = firstsize;
179 cursize = nextsize(cursize)) {
181 for (i = 0; i < cursize; i++) {
182 for (j = 0; j < ndirs; j++) {
183 filename((i + j) % cursize, j, name);
184 close(creat(name, 0666));
187 for (i = 0; i < cursize * stats; i++) {
188 for (j = 0; j < ndirs; j++) {
189 filename((i + j) % cursize, j, name);
193 for (j = 0; j < ndirs; j++) {
194 filename(0, j, name);
195 name[dirchars] = '\0';
196 dirp = opendir(name);
197 while (readdir(dirp))
201 for (i = 0; i < cursize; i++) {
202 for (j = 0; j < ndirs; j++) {
203 filename((i + j) % cursize, j, name);
207 printf("%d %.3f\n", cursize,
208 (now() - stime) * 1.0e3 / (cursize * ndirs));
210 for (j = 0; j < ndirs; j++) {
211 filename(0, j, name);
212 name[dirchars] = '\0';
219 filename(int idx, int dir, char *name)
221 static char hexc[16] = "0123456789abcdef";
224 for (i = dirchars - 1; i >= 0; i--)
225 *name++ = hexc[(dir >> (4 * i)) & 0xf];
227 name += pfxchars; /* skip pfx a's */
228 for (i = minchars - 1; i >= 0; i--)
229 *name++ = hexc[(idx >> (4 * i)) & 0xf];
234 hexchars(uint_t maxval)
238 if (maxval < 16 * 16)
240 if (maxval < 16 * 16 * 16)
242 if (maxval < 16 * 16 * 16 * 16)
244 if (maxval < 16 * 16 * 16 * 16 * 16)
246 if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
248 if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
254 nextsize(uint_t cursize)
263 if (n > (double)lastsize + 0.5)
264 return lastsize + 1; /* i.e. out of bounds */
265 else if ((uint_t)n == cursize)
276 gettimeofday(&tv, NULL);
277 return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
284 "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
285 "[-l last] [-c nchars] [-n ndirs] [-s nstats]\n");