Home | History | Annotate | Download | only in mongo
      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 
     35 use POSIX;
     36 use File::stat;
     37 
     38 sub 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 --------
     59 sub make_fsys;
     60 sub mongo_x_process;
     61 sub mongo_launcher;
     62 sub set_params;
     63 
     64 #------- main() -------------------------
     65 
     66 if ( $#{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 #--------------------------------
    153 unless (-e $RESDIR) {
    154     print "Creating dir: ${RESDIR} \n";
    155     system("mkdir $RESDIR");
    156 }
    157 
    158 unless ( -e $HTMLDIR ) {
    159     print "Creating dir: ${HTMLDIR} \n";
    160     system("mkdir $HTMLDIR");
    161 }
    162 
    163 #... Compile *.c files if it is necessary
    164 #----------------------------------------
    165 sub 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 
    179 compile("reiser_fract_tree", "-lm");
    180 compile("mongo_slinks");
    181 compile("mongo_read");
    182 compile("map5");
    183 compile("summ");
    184 compile("mongo_compare");
    185 
    186 #... Check the command string parameters
    187 #---------------------------------------
    188 unless ( ($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 
    194 unless ( -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 #----------------------------------------------------------
    203 sub 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 
    211 sub 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 #------------------------------------------------------------------
    230 sub 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 #------------------------------------------------------------------
    375 sub 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 #---------------------------------------------------
    482 sub 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