Skip to content

Instantly share code, notes, and snippets.

@jef-sure
Last active January 30, 2021 17:19
Show Gist options
  • Save jef-sure/dc87eade381c58e6e1ba9bdeea597c47 to your computer and use it in GitHub Desktop.
Save jef-sure/dc87eade381c58e6e1ba9bdeea597c47 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use Benchmark qw(cmpthese);
use Config;
use Inline C => Config =>
# BUILD_NOISY => 1,
# FORCE_BUILD => 1,
OPTIMIZE => " -O3 -march=native";
use Inline C => <<'END_OF_C_CODE';
SV* lines_in_string(SV* sv) {
unsigned i, lines = 0;
STRLEN len;
char *ptr;
ptr = SvPV(sv, len);
for(i = 0; i + 8 <= len; i += 8) {
uint64_t v = *(uint64_t*)(ptr + i) ^ 0x0a0a0a0a0a0a0a0aUL;
lines += !(v & 0xFF00000000000000UL);
lines += !(v & 0xFF000000000000UL);
lines += !(v & 0xFF0000000000UL);
lines += !(v & 0xFF00000000UL);
lines += !(v & 0xFF000000U);
lines += !(v & 0xFF0000U);
lines += !(v & 0xFF00U);
lines += !(v & 0xffU);
}
for(; i < len; ++i) {
if(ptr[i] == '\n') ++lines;
}
if(len && ptr[len - 1] != '\n') ++lines;
return newSVuv(lines);
}
END_OF_C_CODE
my $str = "ab\nc\ndefg\n" x 1048576;
my $lines;
cmpthese - 1, {
m => sub {$lines = () = $str =~ m/\n/g},
tr => sub {$lines = ($str =~ tr/\n//)},
while_dollar => sub {$lines = 0; $lines++ while $str =~ m/$/gsm},
while_n => sub {$lines = 0; $lines++ while $str =~ m/\n/gs},
inlinec => sub {$lines = lines_in_string($str)}
};
print lines_in_string($str) . "\n";
print scalar($str =~ tr/\n//) . "\n";
__END__
Rate while_dollar m while_n tr inlinec
while_dollar 1.92/s -- -47% -61% -99% -100%
m 3.64/s 89% -- -27% -98% -100%
while_n 4.95/s 157% 36% -- -98% -99%
tr 203/s 10442% 5475% 3995% -- -76%
inlinec 852/s 44224% 23340% 17118% 320% --
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment