#!/usr/bin/perl use strict; use warnings; use File::Spec; use File::Path qw(remove_tree); use Cwd qw(getcwd abs_path); my ($files, $depth) = @ARGV; if (!defined $files || !defined $depth) { die "Usage: perl bench.pl \n"; } my $base_dir = getcwd(); my $urn_bin = abs_path(File::Spec->catfile("..", "urn")); my $seed_bin = abs_path("seed.pl"); my $bm_repo = "bm_repo"; my %results; my @actions = qw(Status Add Commit); # Helper to count inodes (files/folders) in the metadata directory sub count_inodes { my $dir = shift; return 0 unless -d $dir; my $count = `find $dir | wc -l`; $count =~ s/\s+//g; return $count; } # Helper to get folder size in KB sub get_size { my $dir = shift; return 0 unless -d $dir; my $size = `du -sk $dir`; $size =~ /^(\d+)/; return $1 || 0; } sub run_benchmark { my ($tool_name) = @_; print "Benchmarking $tool_name...\n"; # 1. Seed the directory system("perl $seed_bin $files $depth > /dev/null 2>&1") == 0 or die "Seeding failed"; chdir($bm_repo) or die "Could not enter $bm_repo: $!"; my $meta_dir = ($tool_name eq "URN") ? ".urn" : ".git"; my $init_cmd = ($tool_name eq "URN") ? "perl $urn_bin init" : "git init"; system("$init_cmd > /dev/null 2>&1"); my %cmds = ( "Status" => ($tool_name eq "URN") ? "perl $urn_bin status" : "git status", "Add" => ($tool_name eq "URN") ? "perl $urn_bin add ." : "git add .", "Commit" => ($tool_name eq "URN") ? "perl $urn_bin commit -m 'bench'" : "git commit -m 'bench'", ); foreach my $action (@actions) { my $cmd = $cmds{$action}; # Capture time metrics via STDERR my $raw = `(/usr/bin/time -l $cmd > /dev/null) 2>&1`; # Parse OpenBSD 'time -l' output my ($real) = $raw =~ /(\d+\.\d+)\s+real/; my ($rss) = $raw =~ /(\d+)\s+maximum resident set size/; my ($maj) = $raw =~ /(\d+)\s+page faults caused by physical I\/O/; my ($min) = $raw =~ /(\d+)\s+page reclaims by virtual memory/; $results{$action}{$tool_name} = { real => $real // "0.00", rss => $rss ? sprintf("%.1fM", $rss / 1024 / 1024) : "0M", fault => sprintf("%d/%d", $maj // 0, $min // 0), inodes => count_inodes($meta_dir), disk => get_size($meta_dir) . "K", }; } chdir($base_dir) or die $!; remove_tree($bm_repo) if -d $bm_repo; } # Run sequence run_benchmark("URN"); run_benchmark("GIT"); # --- Final Report Formatting --- my $out_file = "BM_ULTIMATE_${files}_${depth}.txt"; open(my $res, '>', $out_file) or die $!; my $fmt = "%-8s | %-32s | %-32s\n"; my $sep = ("-" x 78); print $res "BENCHMARK: $files files @ $depth depth\n$sep\n"; printf $res $fmt, "ACTION", "URN (Time/RSS/Faults/Inodes/Size)", "GIT (Time/RSS/Faults/Inodes/Size)"; print $res "$sep\n"; foreach my $action (@actions) { my $u = $results{$action}{"URN"}; my $g = $results{$action}{"GIT"}; printf $res "%-8s | %5ss %5s %7s %4s %5s | %5ss %5s %7s %4s %5s\n", $action, $u->{real}, $u->{rss}, $u->{fault}, $u->{inodes}, $u->{disk}, $g->{real}, $g->{rss}, $g->{fault}, $g->{inodes}, $g->{disk}; } print $res "$sep\n"; close($res); # Use PAGER for output print "\nComparison complete! Results saved to $out_file\n"; my $pager = $ENV{PAGER} || 'less'; system("$pager $out_file");