#!/usr/bin/env perl use 5.014; use warnings; use Time::HiRes qw/time/; use Benchmark qw/cmpthese timethese/; use Inline 'C'; sub hash_pack($) { join '', sort unpack '(A10)*', shift } sub hash_re($) { join '', sort $_[0] =~ /(\d{10})/g } sub hash_substr($) { my @nums; my $s = shift; while ($s) { push @nums, substr($s,0,10); $s = substr($s,10); } join '',sort @nums; } # Only considers first 3 numbers sub hash_substr2($) { join '', sort substr($_[0],0,10),substr($_[0],10,10),substr($_[0],20,10); } my @funcs = map { "hash_$_" } qw/pack re substr substr2 c/; my @strings = qw/512567000151256700025125670003 512567000251256700015125670003 512567000351256700015125670002/; for my $s (@strings) { printf "%12s(%s) => %s\n", $_, $s, eval "$_(\$s)" for @funcs; } my $s = $strings[0]; cmpthese timethese(-5, { map { $_ => "$_('$s')" } @funcs }); __END__ __C__ /* Try our own splitter sort. This swaps the numbers in-place * as necessary to obtain a sorted order. */ #include #define SIZE 10 #define strswap(s1,s2,size) { \ int i; \ for (i = 0; i < size; i++) { \ s1[i] = s1[i] ^ s2[i]; \ s2[i] = s1[i] ^ s2[i]; \ s1[i] = s1[i] ^ s2[i]; \ } \ } char * hash_c(char *str) { char *n0 = str; char *n1 = str + SIZE; char *n2 = str + SIZE + SIZE; if (strncmp(n0, n1, SIZE) > 0) strswap(n0, n1, SIZE); if (strncmp(n1, n2, SIZE) > 0) strswap(n1, n2, SIZE); if (strncmp(n0, n1, SIZE) > 0) strswap(n0, n1, SIZE); return str; } #### hash_pack(512567000151256700025125670003) => 512567000151256700025125670003 hash_re(512567000151256700025125670003) => 512567000151256700025125670003 hash_substr(512567000151256700025125670003) => 512567000151256700025125670003 hash_substr2(512567000151256700025125670003) => 512567000151256700025125670003 hash_c(512567000151256700025125670003) => 512567000151256700025125670003 hash_pack(512567000251256700015125670003) => 512567000151256700025125670003 hash_re(512567000251256700015125670003) => 512567000151256700025125670003 hash_substr(512567000251256700015125670003) => 512567000151256700025125670003 hash_substr2(512567000251256700015125670003) => 512567000151256700025125670003 hash_c(512567000151256700025125670003) => 512567000151256700025125670003 hash_pack(512567000351256700015125670002) => 512567000151256700025125670003 hash_re(512567000351256700015125670002) => 512567000151256700025125670003 hash_substr(512567000351256700015125670002) => 512567000151256700025125670003 hash_substr2(512567000351256700015125670002) => 512567000151256700025125670003 hash_c(512567000151256700025125670003) => 512567000151256700025125670003 Benchmark: running hash_c, hash_pack, hash_re, hash_substr, hash_substr2 for at least 5 CPU seconds... hash_c: 6 wallclock secs ( 5.71 usr + 0.00 sys = 5.71 CPU) @ 4606276.36/s (n=26301838) hash_pack: 6 wallclock secs ( 5.07 usr + 0.00 sys = 5.07 CPU) @ 646938.07/s (n=3279976) hash_re: 6 wallclock secs ( 5.03 usr + 0.00 sys = 5.03 CPU) @ 422000.20/s (n=2122661) hash_substr: 5 wallclock secs ( 5.04 usr + 0.00 sys = 5.04 CPU) @ 328204.96/s (n=1654153) hash_substr2: 4 wallclock secs ( 5.14 usr + 0.00 sys = 5.14 CPU) @ 965458.95/s (n=4962459) Rate hash_substr hash_re hash_pack hash_substr2 hash_c hash_substr 328205/s -- -22% -49% -66% -93% hash_re 422000/s 29% -- -35% -56% -91% hash_pack 646938/s 97% 53% -- -33% -86% hash_substr2 965459/s 194% 129% 49% -- -79% hash_c 4606276/s 1303% 992% 612% 377% --