| Algorithm-Diff-XS documentation | Contained in the Algorithm-Diff-XS distribution. |
Algorithm::Diff::XS - Algorithm::Diff with XS core loop
# Drop-in replacement to Algorithm::Diff, but "compact_diff"
# and C<LCSidx> will run much faster for large data sets.
use Algorithm::Diff::XS qw( compact_diff LCSidx );
This module is a simple re-packaging of Joe Schaefer's excellent but not very well-known Algorithm::LCS with a drop-in interface that simply re-uses the installed version of the Algorithm::Diff module.
Note that only the LCSidx function is optimized in XS at the
moment, which means only compact_diff will get significantly
faster for large data sets, while diff and sdiff will run
in identical speed as Algorithm::Diff.
Rate Algorithm::Diff Algorithm::Diff::XS Algorithm::Diff 14.7/s -- -98% Algorithm::Diff::XS 806/s 5402% --
The benchmarking script is as below:
my @data = ([qw/a b d/ x 50], [qw/b a d c/ x 50]);
cmpthese( 500, {
'Algorithm::Diff' => sub {
Algorithm::Diff::compact_diff(@data)
},
'Algorithm::Diff::XS' => sub {
Algorithm::Diff::XS::compact_diff(@data)
},
});
Algorithm::Diff, Algorithm::LCS.
Audrey Tang <cpan@audreyt.org>
Copyright 2008 by Audrey Tang <cpan@audreyt.org>.
Contains derived code copyrighted 2003 by Joe Schaefer, <joe+cpan@sunstarsys.com>.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Algorithm-Diff-XS documentation | Contained in the Algorithm-Diff-XS distribution. |
package Algorithm::Diff::XS; use 5.006; use strict; use warnings; use vars '$VERSION'; use Algorithm::Diff; BEGIN { $VERSION = '0.04'; require XSLoader; XSLoader::load( __PACKAGE__, $VERSION ); my $code = do { open my $fh, '<', $INC{'Algorithm/Diff.pm'} or die "Cannot read $INC{'Algorithm/Diff.pm'}: $!"; local $/; <$fh>; }; { no warnings; local $@; $code =~ s/Algorithm::Diff/Algorithm::Diff::XS/g; $code =~ s/sub LCSidx/sub LCSidx_old/g; $code = "#line 1 " . __FILE__ . "\n$code"; eval $code; die $@ if $@; } no warnings 'redefine'; sub LCSidx { my $lcs = Algorithm::Diff::XS->_CREATE_; my ( @l, @r ); for my $chunk ( $lcs->_LCS_(@_) ) { push @l, $chunk->[0]; push @r, $chunk->[1]; } return ( \@l, \@r ); } } sub _line_map_ { my $ctx = shift; my %lines; push @{ $lines{ $_[$_] } }, $_ for 0 .. $#_; # values MUST be SvIOK \%lines; } sub _LCS_ { my ( $ctx, $a, $b ) = @_; my ( $amin, $amax, $bmin, $bmax ) = ( 0, $#$a, 0, $#$b ); while ( $amin <= $amax and $bmin <= $bmax and $a->[$amin] eq $b->[$bmin] ) { $amin++; $bmin++; } while ( $amin <= $amax and $bmin <= $bmax and $a->[$amax] eq $b->[$bmax] ) { $amax--; $bmax--; } my $h = $ctx->_line_map_( @$b[ $bmin .. $bmax ] ); # line numbers are off by $bmin return $amin + _core_loop_( $ctx, $a, $amin, $amax, $h ) + ( $#$a - $amax ) unless wantarray; my @lcs = _core_loop_( $ctx, $a, $amin, $amax, $h ); if ( $bmin > 0 ) { $_->[1] += $bmin for @lcs; # correct line numbers } map( [ $_ => $_ ], 0 .. ( $amin - 1 ) ), @lcs, map( [ $_ => ++$bmax ], ( $amax + 1 ) .. $#$a ); } 1; __END__