in reply to Re^6: Order of evaluation/interpolation of references (UPDATED)
in thread Order of evaluation/interpolation of references
Reguarding the update, I believe you're suggesting it would be more efficient to implement
$a.$b.$c.$d
as
concat_assign( concat_assign( concat_assign( copy($a), $b ), $c, ), $d )
rather than how it's actually implemented. However, I believe it's being implemented as the following, which is practically the same (ever so slightly better):
concat_assign( concat_assign( concat( $a, $b ), $c, ), $d )
I believe that's what's causing the "S" to appear in concat's flags.
$ perl -MO=Concise,-exec -e'$a.$b.$c.$d' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v:{ 3 <#> gvsv[*a] s 4 <#> gvsv[*b] s 5 <2> concat[t3] sK/2 6 <#> gvsv[*c] s 7 <2> concat[t5] sKS/2 8 <#> gvsv[*d] s 9 <2> concat[t7] vKS/2 a <@> leave[1 ref] vKP/REFC -e syntax OK
But the problem with both of the approaches is that enlarging the string buffer requires copying it (at least on this Debian machine), so the "buk" and current version is usually more expensive (6 bytes rather than 3) than the naïve one I had posted.
A string buffer is only given 4 extra bytes when it's grown, which is pityful. (In comparison, arrays are given N+4 extra elements!) Aside from adding more padding, one could convert concat into an N-ary operator rather than a binary operator.
sub concat_list :lvalue { my $tot_len; $tot_len += length($_) for @_; my $buf = ''; # Allocate $tot_len bytes. $buf .= $_ for @_; $buf }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Optimising concat (was Order of evaluation/interpolation of references)
by BrowserUk (Patriarch) on Mar 09, 2012 at 02:46 UTC | |
by ikegami (Patriarch) on Mar 09, 2012 at 23:05 UTC | |
by ikegami (Patriarch) on Mar 09, 2012 at 03:02 UTC |