From 1b64a87816c06526229f9dc03b12f1092541ae59 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Wed, 29 Apr 2026 14:05:46 +0800 Subject: Fix mtime change <1s bug. --- bm/bm_rebase.pl | 83 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 33 deletions(-) (limited to 'bm/bm_rebase.pl') diff --git a/bm/bm_rebase.pl b/bm/bm_rebase.pl index 3cb0fd5..e89e7f5 100644 --- a/bm/bm_rebase.pl +++ b/bm/bm_rebase.pl @@ -1,10 +1,13 @@ #!/usr/bin/perl use strict; use warnings; +use File::Copy; use File::Spec; -use File::Path qw(remove_tree); +use File::Path qw(remove_tree make_path); use File::Find; +use File::Basename; use Cwd qw(getcwd abs_path); +use Time::HiRes qw(time); my ($files, $depth, $total_commits, $file_perc, $change_perc) = @ARGV; if (!defined $files || !defined $depth || !defined $total_commits || !defined $file_perc || !defined $change_perc) { @@ -14,15 +17,16 @@ if (!defined $files || !defined $depth || !defined $total_commits || !defined $f 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 $bm_repo = "sandbox"; my $sample_rate = int($total_commits / 5) || 1; my %results; my $initial_repo_size = "0 KB"; - my $rebase_count = 0; my %last_base_hashes; +my $global_tick = 0; + sub get_size { my $dir = shift; return "0 KB" unless -d $dir; @@ -62,10 +66,7 @@ sub run_rebase_benchmark { remove_tree($bm_repo) if -d $bm_repo; system("perl $seed_bin $files $depth > /dev/null 2>&1"); - # Capture raw directory size before VCS initialization - if ($initial_repo_size eq "0 KB") { - $initial_repo_size = get_size($bm_repo); - } + if ($initial_repo_size eq "0 KB") { $initial_repo_size = get_size($bm_repo); } chdir($bm_repo) or die $!; @@ -84,19 +85,37 @@ sub run_rebase_benchmark { my $num_to_change = int(scalar(@file_list) * ($file_perc / 100)) || 1; my @target_files = @file_list[0 .. $num_to_change - 1]; - for my $i (1 .. $total_commits) { - for my $target (@target_files) { - open(my $fh, '<', $target) or next; - my @lines = <$fh>; - close($fh); + for my $i (2 .. $total_commits) { + my $debug_dir = "/tmp/urn/commit_$i"; + make_path($debug_dir) unless -d $debug_dir; - my $lines_to_change = int(scalar(@lines) * ($change_perc / 100)) || 1; - splice(@lines, 0, $lines_to_change, "Commit $i: block change\n"); - - if (open(my $out, '>', $target)) { - print $out @lines; - close($out); - } + for my $target (@target_files) { + open(my $fh, '<:raw', $target) or die "Read fail: $target - $!"; + my $content = do { local $/; <$fh> }; + close($fh); + + $global_tick++; + my $ts = time(); + my $header = "C$i-T$ts-N$global_tick "; + + my $total_bytes = length($content); + my $min_len = length($header); + my $to_change = int($total_bytes * ($change_perc / 100)); + + $to_change = $min_len if $to_change < $min_len; + $to_change = $total_bytes if $to_change > $total_bytes; + + my $new_segment = substr($header . ("." x $to_change), 0, $to_change); + substr($content, 0, $to_change, $new_segment); + + open(my $out, '>:raw', $target) or die "Write fail: $target - $!"; + print $out $content; + close($out); + + my $target_name = basename($target); + copy($target, "$debug_dir/$target_name") or warn "Backup failed: $!"; + + utime(undef, undef, $target); } my $cmd = ($tool_name eq "URN") @@ -104,14 +123,17 @@ sub run_rebase_benchmark { : "git add . && git commit -m 'c$i'"; if ($i % $sample_rate == 0 || $i == $total_commits) { - my $stats = `/usr/bin/time -l sh -c "$cmd" 2>&1 > /dev/null`; - my ($real, $rss, $maj, $min) = (0, 0, 0, 0); - if ($stats =~ /(\d+\.\d+)\s+real/) { $real = $1; } - if ($stats =~ /(\d+)\s+maximum resident set size/) { $rss = sprintf("%.2f MB", $1 / 1024 / 1024); } - if ($stats =~ /(\d+)\s+page reclaims/) { $min = $1; } - if ($stats =~ /(\d+)\s+page faults/) { $maj = $1; } + my $raw_output = `/usr/bin/time -l sh -c "$cmd" 2>&1`; + + if ($tool_name eq "URN") { + track_rebases(); + } - if ($tool_name eq "URN") { track_rebases(); } + my ($real, $rss, $maj, $min) = (0, 0, 0, 0); + $real = $1 if $raw_output =~ /(\d+\.\d+)\s+real/; + $rss = sprintf("%.2f MB", $1 / 1024 / 1024) if $raw_output =~ /(\d+)\s+maximum resident set size/; + $min = $1 if $raw_output =~ /(\d+)\s+page reclaims/; + $maj = $1 if $raw_output =~ /(\d+)\s+page faults/; my $meta = ($tool_name eq "URN") ? ".urn" : ".git"; $results{$i}{$tool_name} = { @@ -124,11 +146,10 @@ sub run_rebase_benchmark { print " [Commit $i] $tool_name sampled.\n"; } else { system("$cmd > /dev/null 2>&1"); - if ($tool_name eq "URN") { track_rebases(); } + track_rebases() if $tool_name eq "URN"; } } chdir($base_dir); - remove_tree($bm_repo); } $rebase_count = 0; @@ -141,7 +162,6 @@ open(my $res, '>', $out_file) or die $!; print $res "=============================================================\n"; print $res " REBASE BENCHMARK: $files files ($total_commits commits)\n"; print $res " CONDITIONS: Depth=$depth, Files Mod=$file_perc%, Change=$change_perc%\n"; -print $res " INITIAL RAW DATA SIZE: $initial_repo_size\n"; print $res "=============================================================\n\n"; foreach my $i (sort { $a <=> $b } keys %results) { @@ -158,10 +178,7 @@ foreach my $i (sort { $a <=> $b } keys %results) { printf $res "%-15s | %20s | %20s\n", "Repo size", $u->{size}, $g->{size}; print $res "-------------------------------------------------------------\n\n"; } - print $res "TOTAL URN REBASES: $rebase_count\n"; close($res); -my $pager = $ENV{PAGER} || 'less'; -exec $pager, $out_file; - +exec "less $out_file"; -- cgit v1.2.3