PATCH: Speed up direct string concatenation by 20+%!

Larry Hastings larry at hastings.org
Fri Sep 29 10:34:42 EDT 2006


Steve Holden wrote:

> you should diff your source against the current
> SVN repository and lodge that diff as a patch on SourceForge.

Okay, I'll try to do that today.


> Your suggested bug isn't, I think a real bug in the current
> implementation because as I understand it Python strings do always
> include a trailing null byte to act as a terminator when the string
> is passed to C code in extensions.

Ah!  Excellent point.  So the Python source tree *does* have an
official position on what the first byte of a zero-length string should
be.  I'll fix my code so that is ensured.


> Nice idea, though. You might also see how it does on tasks like
>
> s = ""
> for i in range(100000):
>     s += "a"

Sure.  Here are the results, but with range (10000000):
	Python 2.5 release: 31.0s
	Python 2.5 locally built: 30.7s
	Python 2.5 concat: 4.4s
        % Improvement: *697%*!

Woah!  Thanks for suggesting a benchmark where it really shines :)

The real big win here is storing eight pointers per concatenation
object.  That means 1/8th as many objects created/destroyed.

In testing your suggested benchmark, it overflowed the stack
when freeing the concatenation tree.  So I changed deallocation
of string concatenation objects so it's iterative down the
left-hand side like rendering; now it's happy again.  Thanks
again for suggesting the test.

It would still blow up if you ran
  s = ""
  for i in range(10000000):
    s = "a" + s
because it's only clever about recursion down the left-hand side.
So my advice is, don't.  :)

> Also note that some optimisation has recently been performed on string
> concatenation, which I presume your code has already taken into account.

Totally.  I'm just glad there was something left for me to contribute!


Rob Williscroft wrote:
> On the python 3k list there is a thread about stings becoming "views",
> I think this is similar to what you are doing here.

As I understand it, sort-of.  Definitely moreso in my section on THE
FUTURE--adding another subtype of string for slices which point into
other strings.  I believe views are more sophisticated however.


Felipe Almeida Lessa wrote:
> What about "a + b"? Or "a + b + c"? Does it have a large overhead on
> small string concatenations?

It's *slightly* slower for two:

def addTwoThings(a, b):
    return a + b
for i in range(10000000):
    x = addTwoThings("aaa", "bbb")

	Python 2.5 release: 6.219s
	Python 2.5 locally built: 6.219s
	Python 2.5 concat: 6.234s
	% improvement: -0.03%

But starts paying off already, even with three:

def addThreeThings(a, b, c):
    return a + b + c
for i in range(10000000):
    x = addThreeThings("aaa", "bbb", "ccc")

	Python 2.5 release: 7.9s
	Python 2.5 locally built: 7.7s
	Python 2.5 concat: 7.2s
	% improvement: 6.94%

Note that I was lazy and only did one benchmark run apiece.

Also, keep in mind that memory utilization will be a little higher
with the string concatenation objects.


Carl Friedrich Bolz wrote:
> Robin Becker wrote:
> > wouldn't this approach apply to other additions eg list+list seq+seq etc
> > etc.
> no, I think it depends on strings being immutable.

Exactly.


/larry/




More information about the Python-list mailing list