[Python-de] types.SetType

Stefan Schwarzer sschwarzer at sschwarzer.net
Mo Feb 12 17:55:52 CET 2007


Hallo Hans-Peter, Hallo Diez,

On 2007-02-12 13:36, Diez B. Roggisch wrote:
>> Hmm, nicht ganz, in "hot paths" kann es der Performance zuträglich sein,
>> wenn man sich eine der Evaluierungen spart:
>>   if type(obj) == types.StringType: ...

ich glaube, Python wäre nicht Python, wenn das für die Aufname
eines SetType in types eine Rolle spielen würde. ;-)

> Aber ist
>
> type(obj) == str
>
> denn wirklich langsamer? Es wird erst lokal aufgeloest, danach global  -
> genauso wie modulnamen, oder nicht? Womit der lookup direkt gelingt,
> wohingege ja noch "StringType" in types aufgeloest werden muss.

Wozu vermuten, wenn man messen kann? :-)

Folgende Messwerte sind mit Python 2.5 bestimmt. Es geht mir nur
um die Relationen, deshalb verzichte ich auf die Angabe von
Rechnerdaten. Der Rechner war während der Messungen bei ca. 0 %
Auslastung, abgesehen natürlich von den Messungen selbst.

python /usr/lib/python2.5/timeit.py -r 10 -s "import types; o = ''" "type(o) == types.StringType"
(bzw. anderer Code entsprechend eingesetzt) Den timeit-Lauf habe
ich jeweils mehrmals wiederholt und, wie in der Doku empfohlen,
den kleinsten Wert genommen.

type(o) == types.StringType         0.571 usec
type(o) is types.StringType         0.523 usec
type(o) == str                      0.449 usec
type(o) is str                      0.405 usec
isinstance(o, types.StringType)     0.519 usec
isinstance(o, str)                  0.412 usec

Der Vergleich mit "is" ist erwartungsgemäß schneller als mit
"==", da nur ein Zeiger-Vergleich durchgeführt werden muss.
"isinstance(o, str)" ist praktisch genau so schnell wie
"type(o) is str". In den meisten Fällen will man wohl die
abgeleiteten Klassen mit erwischen, so dass aus meiner Sicht auch
unter dem Geschwindigkeits-Aspekt nichts gegen isinstance
spricht.

Lookups abkürzen
----------------

Ich habe auch getestet, wie sich die Erstellung eines Namens im
lokalen Namensraum auswirkt.

python /usr/lib/python2.5/timeit.py -r 10 -s "from test import str_global" "str_global()"

mit

def str_global():
    o = ""
    for i in xrange(1000):
        isinstance(o, str)

def str_lokal():
    lstr = str
    o = ""
    for i in xrange(1000):
        isinstance(o, lstr)

str_global                          433 usec
str_lokal                           371 usec

Man kann das "Nachschlagen" des str-Typs durch Anlegen eines
lokalen Alias-Namens also potenziell deutlich beschleunigen.

Abschließend möchte ich darum bitten, nicht zu Tempo-Fanatikern
zu werden; die meisten Tuning-Maßnahmen sind wohl unnötig. :-) In
den obigen Beispielen geht es um Laufzeiten von einer halben
Millisekunde!

Bei der Gelegenheit etwas "Eigenwerbung":
http://sschwarzer.com/download/optimization_europython2006.pdf

Beschleunigte Grüße ;-)
Stefan