From 9ffd39ab75dd662df22fcdafbf7f740838acc898 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Wed, 13 Nov 2013 18:10:49 -0800 Subject: =?UTF-8?q?Allow=20PADTMPs=E2=80=99=20strings=20to=20be=20swiped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While copy-on-write does speed things up, it is not perfect. Take this snippet for example: $a = "$b$c"; $a .= $d; The concatenation operator on the rhs of the first line has its own scalar that it reuses every time that operator is called (its target). When the assignment happens, $a and that target share the same string buffer, which is good, because we didn’t have to copy it. But because it is shared between two scalars, the concatenation on the second line forces it to be copied. While copy-on-write may be fast, string swiping surpasses it, because it has no later bookkeeping overhead. If we allow stealing targets’ strings, then $a = "$b$c" no longer causes $a to share the same string buffer as the target; rather, $a steals that buffer and leaves the tar- get undefined. The result is that neither ‘$a =’ nor ‘$a .= $d’ needs to copy any strings. Only the "$b$c" will copy strings (unavoidably). This commit only applies that to long strings, however. This is why: Simply swiping the string from any swipable TARG (which I tried at first) resulted in a significant slowdown. By swiping the string from a TARG that is going to be reused (as opposed to a TEMP about to be freed, which is where swipe was already happening), we force it to allocate another string next time, greatly increasing the number of malloc calls. malloc overhead exceeds the overhead of copying short strings. I tried swiping TARGs for short strings only when the buffer on the lhs was not big enough for a copy (or there wasn’t one), but simple benchmarks with mktables show that even checking SvLEN(dstr) is enough to slow things down, since the speed-up this provides is minimal where short strings are involved. Then I tried checking just the string length, and saw a consistent speed increase. So that’s what this patch uses. Programs using short strings will not benefit. Programs using long strings may see a 1.5% increase in speed, due to fewer string copies. --- ext/Devel-Peek/t/Peek.t | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ext') diff --git a/ext/Devel-Peek/t/Peek.t b/ext/Devel-Peek/t/Peek.t index ed4799cbef..d0f8270309 100644 --- a/ext/Devel-Peek/t/Peek.t +++ b/ext/Devel-Peek/t/Peek.t @@ -509,7 +509,7 @@ do_test('string with Unicode', PV = $ADDR "\\\214\\\101\\\0\\\235\\\101"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\] CUR = 5 LEN = \\d+ - COW_REFCNT = 1 + COW_REFCNT = 1 # $] < 5.019006 '); } else { do_test('string with Unicode', @@ -521,7 +521,7 @@ do_test('string with Unicode', PV = $ADDR "\\\304\\\200\\\0\\\310\\\200"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\] CUR = 5 LEN = \\d+ - COW_REFCNT = 1 + COW_REFCNT = 1 # $] < 5.019006 '); } @@ -549,7 +549,7 @@ do_test('reference to hash containing Unicode', PV = $ADDR "\\\235\\\101"\\\0 \[UTF8 "\\\x\{200\}"\] CUR = 2 LEN = \\d+ - COW_REFCNT = 1 + COW_REFCNT = 1 # $] < 5.019006 ', '', $] > 5.009 ? $] >= 5.015 @@ -580,7 +580,7 @@ do_test('reference to hash containing Unicode', PV = $ADDR "\\\310\\\200"\\\0 \[UTF8 "\\\x\{200\}"\] CUR = 2 LEN = \\d+ - COW_REFCNT = 1 + COW_REFCNT = 1 # $] < 5.019006 ', '', $] > 5.009 ? $] >= 5.015 -- cgit v1.2.1