str performance in python

88

While profiling a piece of python code (python 2.6 up to 3.2), I discovered that the str method to convert an object (in my case an integer) to a string is almost an order of magnitude slower than using string formatting.

Here is the benchmark

>>> from timeit import Timer
>>> Timer('str(100000)').timeit()
0.3145311339386332
>>> Timer('"%s"%100000').timeit()
0.03803517023435887

Does anyone know why this is the case? Am I missing something?

Luca Sbardella
sumber
2
Dan bagaimana dengan'{}'.format(100000)
wim
Itu yang paling lambat tapi juga paling fleksibel.
Luca Sbardella

Jawaban:

106

'%s' % 100000 dievaluasi oleh kompilator dan setara dengan konstanta pada waktu proses.

>>> import dis
>>> dis.dis(lambda: str(100000))
  8           0 LOAD_GLOBAL              0 (str)
              3 LOAD_CONST               1 (100000)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda: '%s' % 100000)
  9           0 LOAD_CONST               3 ('100000')
              3 RETURN_VALUE        

% dengan ekspresi run-time tidak (secara signifikan) lebih cepat dari str :

>>> Timer('str(x)', 'x=100').timeit()
0.25641703605651855
>>> Timer('"%s" % x', 'x=100').timeit()
0.2169809341430664

Perhatikan bahwa strmasih sedikit lebih lambat, seperti yang dikatakan @DietrichEpp, ini karenastr melibatkan operasi pencarian dan pemanggilan fungsi, sementara %mengkompilasi ke satu bytecode langsung:

>>> dis.dis(lambda x: str(x))
  9           0 LOAD_GLOBAL              0 (str)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda x: '%s' % x)
 10           0 LOAD_CONST               1 ('%s')
              3 LOAD_FAST                0 (x)
              6 BINARY_MODULO       
              7 RETURN_VALUE        

Tentu saja hal di atas berlaku untuk sistem yang saya uji (CPython 2.7); implementasi lain mungkin berbeda.

georg
sumber
Indeed this looks like the reason, I just tried myself and string formatting is just about 5% faster than str. Thanks for answer. No reason to change code everywhere :-)
Luca Sbardella
2
To elaborate further: str is a name that can be rebound to something other than the string type, but string formatting - i.e. the str.__mod__ method - cannot be replaced, which permits the compiler to do the optimization. The compiler doesn't do very much in the way of optimization, but it does more than you might think :)
Karl Knechtel
4
... dan pelajaran yang bisa dipelajari di sini adalah: jangan pernah menggunakan literal dalam tes seperti ini!
UncleZeiv
Entri blog khusus ini mungkin menarik bagi Anda: skymind.com/~ocrow/python_string . Ini berisi bagan tolok ukur untuk berbagai metode penggabungan string yang serupa dengan yang Anda berikan di atas.
Aaron Newton
14

Salah satu alasan yang terlintas dalam pikiran adalah fakta yang str(100000)melibatkan pencarian global, tetapi "%s"%100000tidak. The strglobal yang harus mendongak dalam lingkup global. Ini tidak memperhitungkan seluruh perbedaan:

>>> Timer('str(100000)').timeit()
0.2941889762878418
>>> Timer('x(100000)', 'x=str').timeit()
0.24904918670654297

Seperti dicatat oleh thg435 ,

>>> Timer('"%s"%100000',).timeit()
0.034214019775390625
>>> Timer('"%s"%x','x=100000').timeit()
0.2940788269042969
Dietrich Epp
sumber