mboost-dp1

Python % formattering er stadig hurtigst?


Gå til bund
Gravatar #1 - larsp
20. jul. 2023 06:53
Når man skal formatere strenge i Python anbefales det i dag at bruge f strings eller .format() funktionen. Den printf lignende metode med % operatoren er uelsket og ligefrem i fare for at blive deprecated (siger onde tunger).

Men, jeg har lige testet performance for disse tre metoder (og rå concatenation) på forskellige platforme og % metoden er stadig klart den hurtigste!?

Dette er ikke rent navlepilleri. Vores embeddede platform bruger betydelige ressourcer på at formattere log beskeder.

Test kode: https://gist.github.com/larspontoppidan/1846920096...

Embedded platform: (tallene er sekunder, lower is better)
Python 3.8.5 (default, Jul 20 2020, 13:26:22)
[GCC 10.2.0]
Return value: A typical: 1324 format 3.46 example including a string
format: 18.23917683196487
%: 12.374120479973499
f-string: 17.22068142198259
concat: 34.76676397002302


Min PC:
Python 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0]
Return value: A typical: 1324 format 3.46 example including a string
format: 0.5257152650010539
%: 0.3905754190054722
f-string: 0.5616940990003059
concat: 0.8094751190001261


Det kunne være sjovt at se resultatet på andre platforme og Python versioner, f.eks. hvis nogen har en 3.13 kørende?
Gravatar #2 - arne_v
20. jul. 2023 19:16
Med:

print('format: ', timeit.repeat("test1(p1, p2, p3)", globals=globals(), repeat=3))
print('%: ', timeit.repeat("test2(p1, p2, p3)", globals=globals(), repeat=3))
print('f-string: ', timeit.repeat("test3(p1, p2, p3)", globals=globals(), repeat=3))
print('concat: ', timeit.repeat("test4(p1, p2, p3)", globals=globals(), repeat=3))

(jeg kan godt lide at vide om resultaterne er stabile)

C:\Work>\Python\Python311\python.exe pyfp.py
Python 3.11.3 (tags/v3.11.3:f3909b8, Apr 4 2023, 23:49:59) [MSC v.1934 64 bit (AMD64)]
Return value: A typical: 1324 format 3.46 example including a string
format: [0.5681810000096448, 0.5004962999955751, 0.4993155999982264]
%: [0.42378779998398386, 0.398592399986228, 0.4277033999969717]
f-string: [0.5517604999768082, 0.5676551999931689, 0.588243699981831]
concat: [0.844788200018229, 0.8755786000110675, 0.8158750000002328]

C:\Work>\Python\pypy3.10-v7.3.12-win64\pypy.exe pyfp.py
Python 3.10.12 (af44d0b8114cb82c40a07bb9ee9c1ca8a1b3688c, Jun 15 2023, 15:42:22)
[PyPy 7.3.12 with MSC v.1929 64 bit (AMD64)]
Return value: A typical: 1324 format 3.46 example including a string
format: [0.5869312, 0.5390538999999999, 0.5935433000000001]
%: [0.09742110000000004, 0.07236090000000006, 0.07292270000000012]
f-string: [0.3079854000000002, 0.25733950000000005, 0.2692737999999997]
concat: [0.9822837999999998, 0.9251789000000001, 0.9301287]

arne@arnepc6:~$ python3 pyfp.py
Python 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0]
Return value: A typical: 1324 format 3.46 example including a string
format: [0.44623386300000334, 0.4507667689999977, 0.4380086970000008]
%: [0.32420432899999696, 0.3225424630000049, 0.3208818449999882]
f-string: [0.4708820729999985, 0.46883303200000626, 0.47028266199998825]
concat: [0.6730158360000047, 0.6840254199999976, 0.7510450710000072]

arne@arnepc6:~$ graalvm-jdk-17.0.7+8.1/bin/graalpy pyfp.py
Python 3.10.8 (Tue Jun 06 23:10:10 UTC 2023)
[Graal, Oracle GraalVM, Java 17.0.7]
Return value: A typical: 1324 format 3.46 example including a string
format: [2.873770549999989, 2.4633239350000053, 2.4546683580000206]
%: [1.8407666630000108, 1.7041366120000134, 1.6499060569999813]
f-string: [1.780314801000003, 1.604189856000005, 1.5484403130000146]
concat: [1.4163463769999964, 1.29810271300002, 1.2091784559999894]
Gravatar #3 - larsp
20. jul. 2023 21:35
#2 Ganske interessant. Pypy.exe er godt nok hurtig med % formatering.

Og graalpy .... er hurtigst med concatenation? Skørt.

Min forundring er stadig at % typisk er hurtigst, selvom det er den mindst anbefalede metode. Men som Claus nok ville sige, bør man se bort fra den slags og skrive den pæneste kode. Jeg vil så bare tilføje at pænt og elegant er subjektivt og for mit vedkommende er f strings ikke særligt attraktive, mens % er en af de pæneste løsninger. Men det er nok pga. min C baggrund.

Men jeg har nu lagt i graven idéen om at refaktorere vores kode til at bruge andre formateringsmetoder. Der er kun ulemper og nærmest ingen fordele ved at gøre dette.
Gravatar #4 - arne_v
21. jul. 2023 00:28
larsp (3) skrev:

Pypy.exe er godt nok hurtig med % formatering.


JIT.

larsp (3) skrev:

Og graalpy .... er hurtigst med concatenation? Skørt.


JIT of en langsom % formatering (de andre ender uden tvivl i C RTL sprintf, men GraalVM ender formentlig i java.lang.String.format).

larsp (3) skrev:

Min forundring er stadig at % typisk er hurtigst, selvom det er den mindst anbefalede metode. Men som Claus nok ville sige, bør man se bort fra den slags og skrive den pæneste kode. Jeg vil så bare tilføje at pænt og elegant er subjektivt og for mit vedkommende er f strings ikke særligt attraktive, mens % er en af de pæneste løsninger. Men det er nok pga. min C baggrund.


Jeg er noget skeptisk ovefor om forskellen betyde noget. Jeg vil formode at log IO tager meget længere tid end log formatering.

Men jeg kan godt også lide printf - når man har lært den så kan man bruge det i de fleste programmeringsprog.
Gravatar #5 - arne_v
24. jul. 2023 14:56
#1

Der er iøvrigt en som lige har postet noget tilsvarende for C# på LinkedIn.

Se:

https://www.linkedin.com/in/davidcallan/recent-act...
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login