• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/perl
2#
3# Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
4#
5
6#
7# Mongo.pl is reiserfs benchmark.
8#
9# To run please use run_mongo script or :
10#
11# # ./mongo.pl reiserfs /dev/xxxx /testfs log1 5
12# or
13# # ./mongo.pl ext2 /dev/xxxx /testfs log2 5
14#
15# 5 - number of processes, you can set any number here
16#
17# Test will format partition /dev/xxxx by 'mkreiserfs' or 'mke2fs'
18# mount it and run given number of processes during each phase :
19# Create, Copy, Symlinks, Read, Stats, Rename and Delete.
20#
21# Also, the program calc fragmentations after Create and Copy phases:
22# Fragm = number_of_fragments / number_of_files
23# (Current version use the files more than 16KB to calc Fragm.)
24#
25# You can find the same results in files : log, log.tbl, log_table
26#
27# log       - raw results
28# log.tbl   - results for compare program
29# log_table - results in table form
30#
31
32$EXTENDED_STATISTICS = 1;
33
34
35use POSIX;
36use File::stat;
37
38sub print_usage {
39
40        print "\nUsage: mongo.pl <filesystem> <device>";
41	print                  " <mount_point> <log> <processes>\n";
42
43	print "<filesystem>  - the name of filesystem [reiserfs|ext2]\n";
44	print "<device>      - the device for benchmark (e.g. /dev/hda9)\n";
45	print "<mount_point> - mount-point for the filesystem";
46	print " (e.g. /mnt/testfs)\n";
47	print "<log>         - the name prefix for benchmark results\n";
48	print "<processes>   - the number of benchmark processes\n";
49
50	print "\nexamples:\n";
51	print "mongo.pl reiserfs /dev/hda9 /testfs reiserfs_results 1\n";
52	print "mongo.pl ext2 /dev/hda9 /testfs ext2_results 1\n";
53
54	print "\nThe results will be put in ./results directory\n";
55}
56
57
58#------- Subroutines declaration --------
59sub make_fsys;
60sub mongo_x_process;
61sub mongo_launcher;
62sub set_params;
63
64#------- main() -------------------------
65
66if ( $#{ARGV} != 4 ) {
67        print_usage;
68	exit(0);
69    }
70
71#--------------------------------------------
72# Set working directories
73#--------------------------------------------
74$TOPDIR  = "$ENV{PWD}";
75
76$RESDIR  = "${TOPDIR}/results";
77$HTMLDIR = "${RESDIR}/html";
78
79$FILESYSTEM  = $ARGV[0];
80$DEVICE      = $ARGV[1];
81$TESTDIR     = $ARGV[2];
82$PROCESSES   = $ARGV[4];
83
84$LOGFILE     = "${RESDIR}/${ARGV[3]}";
85$LOGFILE2    = "${LOGFILE}_table";
86$LOGFILE3    = "${LOGFILE}.tbl";
87
88$TMPFILE     = "${RESDIR}/mongo_tmp";
89$nproc       = $PROCESSES;
90$READIT      = "${TOPDIR}/mongo_read";
91$SLINKS      = "${TOPDIR}/mongo_slinks";
92
93#-------- reiser_fract_tree parameters----------------
94$x1mb   = 1024 * 1024;
95$x2mb   =    2 * $x1mb;
96$x3mb   =    3 * $x1mb;
97
98$x5mb   =    5 * $x1mb;
99$x50mb  =   50 * $x1mb;
100$x100mb =  100 * $x1mb;
101
102# Total amount of bytes in all files on test partition
103#-----------------------------------------------------
104
105$small_bytes   = $x50mb;
106$medium_bytes  = $x100mb;
107$big_bytes     = $x100mb;
108$large_bytes   = $x100mb;
109
110# Median size of files in bytes for first tree to create
111#-------------------------------------------------------
112$small_size   = 100;
113$medium_size  = 1000;
114$big_size     = 10000;
115$large_size   = 100000;
116
117# Keep the largest file to one fifth (100 million bytes)
118# of the total tree size.
119#-------------------------------------------------------
120$max_file_size = 100000000;
121
122# Yuri Shevchuk says that 0 is the median size
123# in real life, so I believe him.
124#----------------------------------------------
125$median_dir_nr_files = 0;
126
127# This should be larger, change once done testing.
128#-------------------------------------------------
129$bytes_to_consume = 10000000;
130
131$median_file_size = 100;
132$max_file_size    = 1000000;
133
134$median_dir_nr_files    = 100;
135$max_directory_nr_files = 10000;
136
137$median_dir_branching = 0;
138$max_dir_branching    = 1;
139
140# This should be varying, someday....
141#------------------------------------
142$write_buffer_size = 4096;
143
144@numb_of_bytes = ($small_bytes, $medium_bytes, $big_bytes, $large_bytes);
145@size_of_files = ($small_size,  $medium_size,  $big_size,  $large_size);
146
147$reiser_fract_tree_rep_counter = 3;
148
149$total_params = $#{numb_of_bytes};
150
151#... Make directories for results
152#--------------------------------
153unless (-e $RESDIR) {
154    print "Creating dir: ${RESDIR} \n";
155    system("mkdir $RESDIR");
156}
157
158unless ( -e $HTMLDIR ) {
159    print "Creating dir: ${HTMLDIR} \n";
160    system("mkdir $HTMLDIR");
161}
162
163#... Compile *.c files if it is necessary
164#----------------------------------------
165sub compile
166{
167  my $file = shift @_;
168  my $opt = shift @_ if @_ ;
169  my $cfile = $file . ".c";
170  die "source file \"${cfile}\" does not exist" unless (-e  "$cfile");
171  if ( -e "$file" && (stat("$file")->mtime >= stat("$cfile")->mtime)) {
172    print "$file is up to date ...\n";
173  } else {
174    print "Compiling ${cfile} ...\n";
175    system ("gcc $cfile -o $file $opt");
176  }
177}
178
179compile("reiser_fract_tree", "-lm");
180compile("mongo_slinks");
181compile("mongo_read");
182compile("map5");
183compile("summ");
184compile("mongo_compare");
185
186#... Check the command string parameters
187#---------------------------------------
188unless ( ($FILESYSTEM eq "reiserfs") or ($FILESYSTEM eq "ext2") ) {
189    print "mongo.pl: not valid filesystem name: ${FILESYSTEM} \n";
190    print "Usage: mongo.pl <filesystem> <device> <mount_point> <log> <repeat>\n";
191    exit(0);
192}
193
194unless ( -b $DEVICE ) {
195    print "mongo.pl: not valid device: ${DEVICE} \n";
196    print "Usage: mongo.pl <filesystem> <device> <mount_point> <log> <repeat>\n";
197    exit(0);
198}
199
200
201#------- Subroutines --------------------------------------
202#----------------------------------------------------------
203sub get_blocks_usage ($) {
204  my ($mp) = @_;
205  my $df = `df -k $mp | tail -n 1`;
206  chomp $df;
207  my @items = split / +/, $df;
208  return $items[2];
209}
210
211sub make_fsys {
212
213    system ("umount $TESTDIR") ;
214
215    if ( $FILESYSTEM eq "reiserfs" ) {
216	system("echo y | mkreiserfs $DEVICE") ;
217	system("mount -t reiserfs $DEVICE $TESTDIR") ;
218    }
219
220    if ( $FILESYSTEM eq "ext2" ) {
221	system("mke2fs $DEVICE") ;
222	system("mount $DEVICE $TESTDIR") ;
223    }
224}
225
226
227#------------------------------------------------------------------
228# Mongo Launcher
229#------------------------------------------------------------------
230sub mongo_launcher {
231
232    my ($phase_num, $phase_name, $cmd, $dir1, $dir2, $flag, $processes) = @_ ;
233
234
235    print "$phase_num.$phase_name files of median size $median_file_size bytes ($p processes)...\n";
236    print LOG "********* Phase $phase_num: $phase_name files of median size $median_file_size bytes ($p processes) *********\n";
237    $i=0;
238    $total=0;
239
240# eliminate the rep counter and the while
241    while ( $i < $reiser_fract_tree_rep_counter ) {
242	print "$phase_name : ";
243    	print LOG "$phase_name : ";
244	$com = "";
245	$pp=$processes;
246
247	$j=0;
248	while ($pp > 0) {
249	    $pp--;
250
251# the fact that this if statement was necessary indicated you
252# attempted excessive generalization and abstraction where it was not
253# natural to the task that makes the code harder to understand.  put
254# every command on one line to execute.  I like it when I can read a
255# one line command and see what that phase of the test does instead of
256# looking in many places throughout the code.
257
258	    if ($phase_num == 1) {
259    		$com .= "$cmd $dir1-$i-$j $flag";
260	    }
261	    elsif ($phase_num == 2) {
262		$com .= "$cmd $dir1-$i-$j $dir2-$i-$j";
263	    }
264	    elsif ($phase_num == 3) {
265		$com .= "$cmd $dir1-$i-$j "."-type f | while read X; do echo \$X \$X.lnk ; done | $TOPDIR/mongo_slinks ";
266	    }
267	    elsif ($phase_num == 4) {
268		$com .= "$cmd";
269	    }
270	    elsif ($phase_num == 5) {
271		$com .= "$cmd";
272	    }
273	    elsif ($phase_num == 6) {
274		$com .= "$cmd $dir1-$i-$j -type f | perl -e 'while (<>) { chomp; rename (\$_, \"\$_.r\"); };'";
275		#$com .= " & $cmd $dir2-$i-$j "."-type d -exec mv {} {}.r ';'";
276	    }
277	    elsif ($phase_num == 7) {
278		if ($processes > 1) {
279		    $com .= "$cmd $dir1-$i-$j & $cmd $dir2-$i-$j";
280		}
281		else {
282		    $com .= "$cmd $dir1-$i-$j ; $cmd $dir2-$i-$j";
283		}
284	    }
285	    $com .= " & ";
286	    $j++;
287	}
288
289	$com .= " wait";
290	#print $com, "\n";
291
292	@t=`(time -p $com) 2>&1`;
293
294	@tt = split ' ', $t[0];
295    	$res = $tt[1];
296	unless ( $res =~ /\s*\d+/) {
297	    print @t , "\n";
298	    print LOG @t, "\n";
299	} else {
300	    print LOG "$res sec.\n";
301	    print "$res sec.\n";
302	}
303
304	$total += $res;
305    	$i++;
306     }
307
308    print "total $phase_name time: $total sec.\n";
309    print LOG "total $phase_name time: $total sec.\n";
310
311    $ares[$phase_num]=$total;  # ser array of results
312
313    if ($EXTENDED_STATISTICS) {
314	if( $phase_num < 3) {
315	    $used = get_blocks_usage($TESTDIR) - $used0;
316	    if ($phase_num == 1) {
317		$used1=$used;
318	    }elsif($phase_num == 2){
319		$used2=$used;
320	    }
321	    print "Used disk space (df) : $used KB\n";
322	    print LOG "Used disk space (df) : $used KB\n";
323
324	    open (FIND_PIPE, "find $TESTDIR|") || die "cannnot open pipe from \"find\": $!\n";
325	    $dirs = 0;
326	    $files = 0;
327	    $files16 = 0;
328
329	    while(<FIND_PIPE>) {
330		chomp;
331		$st = lstat ($_);
332		if (S_ISDIR($st->mode)) {
333		    $dirs ++;
334		} elsif (S_ISREG($st->mode)) {
335		    $files ++;
336		    $files16 ++ if ($st->size > 16384);
337		}
338	    }
339
340	    close (FIND_PIPE);
341
342	    print "Total dirs: $dirs\n";
343	    print "Total files: $files\n";
344	    print LOG "Total dirs: $dirs\n";
345	    print LOG "Total files: $files\n";
346
347	    #$f=$frag;
348	    $f16  = $files16;
349	    $fr16 =`find $TESTDIR -type f -size +16k | xargs $TOPDIR/map5 | $TOPDIR/summ | tail -n 1 2>&1`;
350	    @ff16= split ' ', $f16;
351	    @ffr16= split ' ', $fr16;
352	    $files16 = $ff16[0];
353	    $frag = $ffr16[0];
354	    $procent = $frag / $files16;
355	    print "Total fragments : $frag \n";
356	    print LOG "Total fragments : $frag \n";
357
358	    printf "Fragments / files :%.3f\n", $procent;
359	    printf LOG "Fragments / files :%.3f\n", $procent;
360	    $frag_res[$phase_num]=$procent;  # ser array of results
361	}
362    }
363
364    system("sync");
365    print "\n";
366    print LOG "\n";
367
368}
369
370# and what is an x process?
371
372#------------------------------------------------------------------
373# MONGO_X_PROCESS ( x is number of processes to run )
374#------------------------------------------------------------------
375sub mongo_x_process {
376
377    my ($processes) = @_ ;
378    $p = $processes;
379
380    make_fsys;       # make and mount the file system
381    $used0 = get_blocks_usage($TESTDIR);
382
383    open LOG,  ">>$LOGFILE"  or die "Can not open log file $LOGFILE\n";
384    open LOG2, ">>$LOGFILE2" or die "Can not open log file $LOGFILE2\n";
385    open LOG3, ">>$LOGFILE3" or die "Can not open log file $LOGFILE2\n";
386
387    print LOG "FILESYSTEM=$FILESYSTEM \n";
388
389    print "\n";
390    if($p == 1) {
391	print "mongo_single_process, the_set_of_param.N=$par_set_n of $total_params \n";
392	print LOG "mongo_single_process, the_set_of_paramN=$par_set_n of $total_params \n";
393    } elsif ($p > 1) {
394        print "mongo_multi_process ($p processes), the_set_of_param.N=$par_set_n of $total_params \n";
395	print LOG "mongo_multi_process ($p processes), the_set_of_paramN=$par_set_n of $total_params \n";
396    }
397
398    print "Results in file : $LOGFILE \n";
399    print "\n";
400
401    $dir1 = "$TESTDIR/testdir1";
402    $dir2 = "$TESTDIR/testdir2";
403    $flag = 0;
404
405    $cmd_1 = "$TOPDIR/reiser_fract_tree $bytes_to_consume $median_file_size $max_file_size $median_dir_nr_files $max_directory_nr_files $median_dir_branching $max_dir_branching $write_buffer_size";
406    $cmd_2 = "cp -r";
407    $cmd_3 = "find";
408    $cmd_4 = "find $TESTDIR -type f | xargs $TOPDIR/mongo_read";
409    $cmd_5 = "find $TESTDIR -type f > /dev/null"; # it should be enough for stat all files. -zam
410    $cmd_6 = "find"; #" $TESTDIR -type f -exec mv {} {}.r ';'";
411    $cmd_7 = "rm -r";
412
413    system("sync");
414    $frag = 0;
415    mongo_launcher ( 1, "Create", $cmd_1, $dir1, $dir2, $flag, $p); # phase 1
416    mongo_launcher ( 2, "Copy  ", $cmd_2, $dir1, $dir2, $flag, $p); # phase 2
417    mongo_launcher ( 3, "Slinks", $cmd_3, $dir1, $dir2, $flag, $p); # phase 3
418    mongo_launcher ( 4, "Read  ", $cmd_4, $dir1, $dir2, $flag, $p); # phase 4
419    mongo_launcher ( 5, "Stats ", $cmd_5, $dir1, $dir2, $flag, $p); # phase 5
420    mongo_launcher ( 6, "Rename", $cmd_6, $dir1, $dir2, $flag, $p); # phase 6
421    mongo_launcher ( 7, "Delete", $cmd_7, $dir1, $dir2, $flag, $p); # phase 7
422
423    print LOG2 "\n";
424    if ($processes > 1) {
425	print LOG2 "MONGO_MULTI_PROCESS ($processes processes) BENCHMARK RESULTS (time in sec.)\n";
426    }else {
427	print LOG2 "MONGO_SINGLE_PROCESS BENCHMARK RESULTS (time in sec.)\n";
428    }
429    print LOG2 "  FILESYSTEM=$FILESYSTEM\n";
430    print LOG2 "  parameters: files=$files, base_size=$median_file_size bytes, dirs=$dirs\n";
431    print LOG2 "--------------------------------------------------------------\n";
432    print LOG2 "Create\tCopy\tSlink\tRead\tStats\tRename\tDelete\n";
433    print LOG2 " time \ttime\ttime\ttime\ttime \t time \t time\n";
434    print LOG2 "--------------------------------------------------------------\n";
435    print LOG2 "$ares[1]\t$ares[2]\t$ares[3]\t$ares[4]\t$ares[5]\t$ares[6]\t$ares[7]\n";
436    print LOG2 "--------------------------------------------------------------\n";
437    print LOG2 "The size of files tree : \n";
438    print LOG2 "         after create = $used1 kb\n";
439    print LOG2 "         after copy   = $used2 kb\n";
440    print LOG2 "\n";
441
442
443    print LOG3 "\n";
444    if ($processes > 1) {
445	print LOG3 "MONGO_MULTI_PROCESS  ($processes)    \n";
446    }else {
447	print LOG3 "MONGO_SINGLE_PROCESS      \n";
448    }
449    print LOG3 "parameters:              \n";
450    print LOG3 "files=$files            \n";
451    print LOG3 "base_size=$median_file_size bytes    \n";
452    print LOG3 "dirs=$dirs              \n";
453    print LOG3 "\n";
454
455    print LOG3 "FSYS=$FILESYSTEM         \n";
456    print LOG3 "(time in sec.)           \n";
457    print LOG3 "Create : $ares[1]\n";
458    print LOG3 "Fragm. : $frag_res[1]\n";
459    print LOG3 "df     : $used1\n\n";
460    print LOG3 "Copy   : $ares[2] \n";
461    print LOG3 "Fragm. : $frag_res[2]\n";
462    print LOG3 "df     : $used2\n\n";
463    print LOG3 "Slinks : $ares[3]\n";
464    print LOG3 "Read   : $ares[4]\n";
465    print LOG3 "Stats  : $ares[5]\n";
466    print LOG3 "Rename : $ares[6] \n";
467    print LOG3 "Delete : $ares[7]\n";
468
469    print LOG3 "\n";
470
471
472    if($processes > 1) {
473	print LOG "******* The end of mongo_multi_process *******";
474    }else {
475	print LOG "******* The end of mongo_single_process *******";
476    }
477}
478
479#---------------------------------------------------
480# Set parameters
481#---------------------------------------------------
482sub set_params {
483    my ($n) = @_ ;
484
485    $bytes_to_consume = $numb_of_bytes[$n];
486    $median_file_size = $size_of_files[$n];
487
488    #$max_file_size    = 1000000;
489
490    #$median_dir_nr_files    = 100;
491    #$max_directory_nr_files = 10000;
492
493    #$median_dir_branching = 0;
494    #$max_dir_branching    = 1;
495
496}
497
498#----------------------------------------------------------
499#           TEST START
500#----------------------------------------------------------
501
502    $par_set_n = 0;
503    foreach $fsize (@size_of_files) {
504	set_params ($par_set_n);
505	mongo_x_process( $nproc );    # run n processes
506	$par_set_n++;
507    }
508    system("umount $TESTDIR");
509    exit;
510
511
512