Live data from Hacker News

Efficient String Concatenation in Python

skymind.com

21–29 of 29 posts

Re: Efficient String Concatenation in Python

#21
post #19

For comparison, PHP has mutable strings. Some totally unscientific averaged benchmarks (Atom D2700, PHP 5.4.4-14 amd64): $buff = ''; for ($i = 0; $i != 100000; ++$i) { $buff .= $i; } Runs in about 0.06s $buff = array(); for ($i = 0; $i != 100000; ++$i) { $buff[] = $i; } $ret = implode('', $buff); Runs slower, in about 0.10s $ret = implode('', range(0, 100000)); Takes roughly the same time, 0.10s

[deleted]

Re: Efficient String Concatenation in Python

#23
post #10
post #9

Earlier quoted context omitted.

Does PyPy have the same heuristic? If not, I wouldn't recommend relying on it.

If not, I would recommend submitting a bug to PyPy.

If GP is referring to CPython patch #980695, it appears to be available in PyPy, but requires an additional flag.

"We have it, just not enabled by default. --objspace-with-strbuf I think" [1]

[1] https://mail.python.org/pipermail/python-dev/2013-February/1...

Re: Efficient String Concatenation in Python

#24
post #8

Note that since this article was written (2004) CPython performs an in-place optimisation for assignments of the form s1 += s2 There are details at point six of http://docs.python.org/2/library/stdtypes.html#sequence-type... , where it also says that str.join() is preferable.

OK, so for fun I did a ran this on my machine (MacBook Pro, 2.53GHz, 10.8.4, 8GB ram, Python 2.7.2 shipped by Apple). I had to emulate the old timing module using code from [1].

    Method 1: 0.115 seconds
    Method 2: I gave up after >120s
    Method 3: 0.265
    Method 4: 0.160
    Method 5: 0.220
    Method 6: 0.098
I ran each one a few times to make sure the times were roughly correct. Method 6 is still the fastest, but the naive method one is really close. it obviously got optimized. Actually, they're all pretty close with the obvious (and hideous) outlier of using MutableString.

EDIT:

I just remembered I have an old version of PyPy (1.8) on my Mac. Thought I'd give that a try.

    Method 1: I gave up after >120s
    Method 2: I gave up after >120s
    Method 3: 0.090 seconds
    Method 4: 0.102
    Method 5: 0.430
    Method 6: 0.102
Method one is a problem again, and method 5 (the pseudo file) is noticeably slower. Otherwise the results aren't too far off.

[1] http://effbot.org/librarybook/timing.htm

Re: Efficient String Concatenation in Python

#25
post #11

I believe that the current most efficient way of doing this is ''.join(map(str, range(n)))

In Python 2, itertools.imap will be faster since it doesn't realize a list. Also, if you are memory constrained, xrange doesn't realize a list either, whereas range does (but the article notes that range was slightly faster than xrange in his tests--I don't know if that's still true in Python 2, the article is 9 years old). In Python 3, the map builtin is basically equivalent what itertools.imap was in Python 2, so i…

I tried it with n=1000 and n=10000, and found that using xrange made it slightly faster, as did using itertools.imap, but the difference was pretty small.

(Here I'm using the stock Python 2.7.1 on a 2011 MacBook Pro.)

Re: Efficient String Concatenation in Python

#27
post #24
post #8

Note that since this article was written (2004) CPython performs an in-place optimisation for assignments of the form s1 += s2 There are details at point six of http://docs.python.org/2/library/stdtypes.html#sequence-type... , where it also says that str.join() is preferable.

OK, so for fun I did a ran this on my machine (MacBook Pro, 2.53GHz, 10.8.4, 8GB ram, Python 2.7.2 shipped by Apple). I had to emulate the old timing module using code from [1]. Method 1: 0.115 seconds Method 2: I gave up after >120s Method 3: 0.265 Method 4: 0.160 Method 5: 0.220 Method 6: 0.098 I ran each one a few times to make sure the times were roughly correct. Method 6 is still the fastest, but the naive metho…

Similar relative results, except that method 1 is always the fastest and even better than method 6. Ran loop count with large numbers (10 million & 30 million) to reduce measurement noise. Profiling was with cProfile on Core i3 2.53Ghz, 6 GB ram, Python 2.7.3 on Ubuntu 12.04

for 10M loop count, method 1 -> 1.599 s, method 6 -> 1.91 s

for 30M loop count,method 1 -> 4.967 s, method 6 -> 5.871 s

Summary: The KISS s1 += s2 always wins

Re: Efficient String Concatenation in Python

#29
post #25
post #11

Earlier quoted context omitted.

In Python 2, itertools.imap will be faster since it doesn't realize a list. Also, if you are memory constrained, xrange doesn't realize a list either, whereas range does (but the article notes that range was slightly faster than xrange in his tests--I don't know if that's still true in Python 2, the article is 9 years old). In Python 3, the map builtin is basically equivalent what itertools.imap was in Python 2, so i…

I tried it with n=1000 and n=10000, and found that using xrange made it slightly faster, as did using itertools.imap, but the difference was pretty small. (Here I'm using the stock Python 2.7.1 on a 2011 MacBook Pro.)

using xrange made it slightly faster

That's what I would expect, since xrange works like a generator; but the internals of its implementation in CPython back when the article ran its original tests were evidently less efficient than they are now.

the difference was pretty small

I suspect that's because the strings being concatenated are really small (the largest will only be 5 bytes for n=10000). I would expect the difference to get bigger as the individual strings get larger.

Post reply on HN