in reply to Using substr to split a string scales as N^2 -- alternatives?

I think the reason for this slowdown is that when constructing support for the lvalue property of substr,

No, it's only done when necessary, and it's not here.

>perl -MO=Concise -e"\substr($_,1)" 2>&1 | find "substr" 5 <@> substr[t4] sKRM/2 ->6 ^ | "M"odifiable => magic created. >perl -MO=Concise -e"$a = substr($_,1)" 2>&1 | find "substr" 5 <@> substr[t3] sK/2 ->6 ^ | Not modifiable => no magic created.

The time is spent creating new strings and assigning them.

Pass 1: Creates a 79,999 char string & copies it into $a's buffer Pass 2: Creates a 79,998 char string & copies it into $a's buffer Pass 3: Creates a 79,997 char string & copies it into $a's buffer ... Pass 79,999: Creates a 1 char string & copies it into $a's buffer Pass 80,000: Creates a 0 char string & copies it into $a's buffer

It's copying (((N-1)+1)(N-1)/2)*2 = (N^2 - N) = 6,399,920,000 bytes!

However, it's possible to do what you want without copying a singly byte! Through a feature called "OOK", Perl can efficiently remove the leading chars of strings when it does so in-place.

$a =~ s/.//s; # Remove leading char with no copying. substr($a, 0, 1, ''); # Remove leading char with no copying.

The latter even returns the character removed! (Well, so does the former if you add a capture.)

Benchmarks:

-------------------- 20,000 Rate substr3 s/// substr4 substr3 1.61/s -- -93% -96% s/// 23.1/s 1336% -- -44% substr4 41.2/s 2460% 78% -- -------------------- 40,000 Rate substr3 s/// substr4 substr3 0.884/s -- -96% -98% s/// 23.1/s 2509% -- -45% substr4 41.6/s 4606% 80% -- -------------------- 80,000 Rate substr3 s/// substr4 substr3 0.445/s -- -98% -99% (warning: unreliable count) s/// 23.4/s 5162% -- -42% substr4 40.1/s 8897% 71% --

The rate is the number of times 80,000 chars can be processed per second. Notice how the 4-arg substr and s/// aren't affected by the length of the input?

Benchmark code

Replies are listed 'Best First'.
Re^2: Using substr to split a string scales as N^2 -- alternatives?
by wol (Hermit) on Jan 05, 2009 at 14:23 UTC
    I know this is supposed to be a Perl focussed forum, so other languages are generally off topic, and this is going off on a pretty tenuous tangent, but orang-utan coders would prefer to implement OOK as follows:
    Ook? Ook. Ook. Ook! Ook! Ook!
    The consequential benchmark results are left as an exercise to the (hairy orange) reader.

    --
    use JAPH;
    print JAPH::asString();