Skip to content

Commit 0b19138

Browse files
neoeinsteinEric Wong
authored andcommitted
git-svn: Make it incrementally faster by minimizing temp files
Currently, git-svn would create a temp file on four occasions: 1. Reading a blob out of the object db 2. Creating a delta from svn 3. Hashing and writing a blob into the object db 4. Reading a blob out of the object db (in another place in code) Any time git-svn did the above, it would dutifully create and then delete said temp file. Unfortunately, this means that between 2-4 temporary files are created/deleted per file 'add/modify'-ed in svn (O(n)). This causes significant overhead and helps the inode counter to spin beautifully. By its nature, git-svn is a serial beast. Thus, reusing a temp file does not pose significant problems. "truncate and seek" takes much less time than "unlink and create". This patch centralizes the tempfile creation and holds onto the tempfile until they are deleted on exit. This significantly reduces file overhead, now requiring at most three (3) temp files per run (O(1)). Signed-off-by: Marcus Griep <marcus@griep.us> Acked-by: Eric Wong <normalperson@yhbt.net>
1 parent e41352b commit 0b19138

1 file changed

Lines changed: 18 additions & 17 deletions

File tree

git-svn.perl

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,7 @@ sub md5sum {
12651265
my $arg = shift;
12661266
my $ref = ref $arg;
12671267
my $md5 = Digest::MD5->new();
1268-
if ($ref eq 'GLOB' || $ref eq 'IO::File') {
1268+
if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
12691269
$md5->addfile($arg) or croak $!;
12701270
} elsif ($ref eq 'SCALAR') {
12711271
$md5->add($$arg) or croak $!;
@@ -1328,6 +1328,7 @@ BEGIN
13281328
}
13291329
}
13301330

1331+
13311332
my (%LOCKFILES, %INDEX_FILES);
13321333
END {
13331334
unlink keys %LOCKFILES if %LOCKFILES;
@@ -3230,13 +3231,11 @@ sub change_file_prop {
32303231

32313232
sub apply_textdelta {
32323233
my ($self, $fb, $exp) = @_;
3233-
my $fh = IO::File->new_tmpfile;
3234-
$fh->autoflush(1);
3234+
my $fh = Git::temp_acquire('svn_delta');
32353235
# $fh gets auto-closed() by SVN::TxDelta::apply(),
32363236
# (but $base does not,) so dup() it for reading in close_file
32373237
open my $dup, '<&', $fh or croak $!;
3238-
my $base = IO::File->new_tmpfile;
3239-
$base->autoflush(1);
3238+
my $base = Git::temp_acquire('git_blob');
32403239
if ($fb->{blob}) {
32413240
print $base 'link ' if ($fb->{mode_a} == 120000);
32423241
my $size = $::_repository->cat_blob($fb->{blob}, $base);
@@ -3251,9 +3250,9 @@ sub apply_textdelta {
32513250
}
32523251
}
32533252
seek $base, 0, 0 or croak $!;
3254-
$fb->{fh} = $dup;
3253+
$fb->{fh} = $fh;
32553254
$fb->{base} = $base;
3256-
[ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
3255+
[ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
32573256
}
32583257

32593258
sub close_file {
@@ -3282,22 +3281,25 @@ sub close_file {
32823281
}
32833282
}
32843283

3285-
my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
3284+
my $tmp_fh = Git::temp_acquire('svn_hash');
32863285
my $result;
32873286
while ($result = sysread($fh, my $string, 1024)) {
32883287
my $wrote = syswrite($tmp_fh, $string, $result);
32893288
defined($wrote) && $wrote == $result
3290-
or croak("write $tmp_filename: $!\n");
3289+
or croak("write ",
3290+
$tmp_fh->filename, ": $!\n");
32913291
}
32923292
defined $result or croak $!;
3293-
close $tmp_fh or croak $!;
32943293

3295-
close $fh or croak $!;
32963294

3297-
$hash = $::_repository->hash_and_insert_object($tmp_filename);
3298-
unlink($tmp_filename);
3295+
Git::temp_release($fh, 1);
3296+
3297+
$hash = $::_repository->hash_and_insert_object(
3298+
$tmp_fh->filename);
32993299
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
3300-
close $fb->{base} or croak $!;
3300+
3301+
Git::temp_release($fb->{base}, 1);
3302+
Git::temp_release($tmp_fh, 1);
33013303
} else {
33023304
$hash = $fb->{blob} or die "no blob information\n";
33033305
}
@@ -3667,7 +3669,7 @@ sub chg_file {
36673669
} elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
36683670
$self->change_file_prop($fbat,'svn:executable',undef);
36693671
}
3670-
my $fh = IO::File->new_tmpfile or croak $!;
3672+
my $fh = Git::temp_acquire('git_blob');
36713673
if ($m->{mode_b} =~ /^120/) {
36723674
print $fh 'link ' or croak $!;
36733675
$self->change_file_prop($fbat,'svn:special','*');
@@ -3686,9 +3688,8 @@ sub chg_file {
36863688
my $atd = $self->apply_textdelta($fbat, undef, $pool);
36873689
my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
36883690
die "Checksum mismatch\nexpected: $exp\ngot: $got\n" if ($got ne $exp);
3691+
Git::temp_release($fh, 1);
36893692
$pool->clear;
3690-
3691-
close $fh or croak $!;
36923693
}
36933694

36943695
sub D {

0 commit comments

Comments
 (0)