Set vs. frozenset Leistung
War ich herumspielens mit Python set
und frozenset
collection-Typen.
Zunächst bin ich davon ausgegangen, dass frozenset
würde, um einen besseren lookup-Leistung als set
, als seine unveränderliche und somit könnte diese Struktur der gespeicherten Elemente.
Jedoch, dies scheint nicht der Fall zu sein, in Bezug auf das folgende experiment:
import random
import time
import sys
def main(n):
numbers = []
for _ in xrange(n):
numbers.append(random.randint(0, sys.maxint))
set_ = set(numbers)
frozenset_ = frozenset(set_)
start = time.time()
for number in numbers:
number in set_
set_duration = time.time() - start
start = time.time()
for number in numbers:
number in frozenset_
frozenset_duration = time.time() - start
print "set : %.3f" % set_duration
print "frozenset: %.3f" % frozenset_duration
if __name__ == "__main__":
n = int(sys.argv[1])
main(n)
Ich ausgeführt dieser code mit beiden CPython und PyPy, gab die folgenden Ergebnisse:
> pypy set.py 100000000
set : 6.156
frozenset: 6.166
> python set.py 100000000
set : 16.824
frozenset: 17.248
Scheint es, dass frozenset
ist tatsächlich langsamer in Bezug auf die lookup-Leistung, sowohl in CPython und PyPy. Hat jemand eine Idee, warum dies der Fall ist? Ich sah nicht in den Implementierungen.
- "als unveränderlich und somit könnte diese Struktur der gespeicherten Elemente" - was genau hast du erwartet, es zu tun? Jede Struktur hat Zugang zu
set
hat auch. - Nun, das ist, was ich verlange. Ich dachte, dass vielleicht frozenset könnte eine Art von vorberechneten hash-Funktion, die wiederum ergeben könnte besser lookup-Leistung.
- Sie müssen berechnen den hash-Wert von jedem Element, das Sie nachschlagen, Punkt. Man kann nicht vorausberechnen hashes hier können Sie testen, einen beliebigen Gegenstand gegen das set. Ich bin mir nicht sicher, wie Sie Sie sich vorstellen, dass diese Optimierung? Elemente im Satz nicht brauchen, um Ihre hash berechnet; Sie wurden bereits eingesteckt in die hash-Tabelle.
- "Sie müssen berechnen den hash-Wert von jedem Element, das Sie nachschlagen, Zeit" ich bin mir dieser Tatsache bewusst, aber immer noch einen festen Satz von Elementen könnten, bieten Möglichkeiten zur Optimierung (z.B., eine perfekte hash-Funktion, erzeugt werden, die zum Zeitpunkt der frozenset generiert wird und werden könnte, wird für die Suche verwendet)
- Haben Sie beseitigt garbage collection Verzögerungen und andere system-timings? Verwenden Sie die
timeit
Modul für das richtige timing Experimente. Versuchen Sie, mit zahlen nicht in beiden zu setzen.frozenset
undset
teilen sich die gleiche Umsetzung, so dass die timing-Unterschiede, die Sie sehen, sind ausschließlich lokal auf Ihrem test. - Ich bin mir nicht bewusst irgendwelche Verknüpfungen gibt. Alle die Berechnung gilt für das Element, das Sie testen gegen den Satz zu finden, der Steckplatz, in dem es möglicherweise einen gleichartigen Gegenstand.
- Ich bin ein wenig spät zur party, aber würde nicht speichern Sie die python-frozenset auf die Funktion Objekt für wiederholte Anrufe wie ein Tupel vs. Liste?
- Ich Stimme mit Sven, dass ein frozenset könnte theoretisch eine bessere Leistung bei lookup-Zeit, indem Sie weitere Berechnung zum Zeitpunkt der Erstellung. Zum Beispiel mit einer hash-Tabelle Implementierung einer hash-Funktion kann so gewählt werden, dass es minimale Kollision unter Hashwerte der Elemente der Menge.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
frozenset
undset
Implementierungen sind weitgehend geteilt;set
ist einfach einfrozenset
mit mutierend Methoden Hinzugefügt, mit der exakt gleichen hashtable-Implementierung. Finden Sie die- Objekte/setobject.c
Quelltext-Datei; die top-level -PyFrozenSet_Type
- definition Aktien-Funktionen mit derPySet_Type
- definition.Gibt es keine Optimierung für ein frozenset hier, als dort ist keine Notwendigkeit, die Berechnung der hashes für die Elemente in die
frozenset
wenn Sie Tests für die Mitgliedschaft. Das Element, das Sie zum testen verwenden gegen den Satz noch braucht, um Ihre hash berechnet, um den richtigen zu finden-slot in der set-Hashtabelle, so dass Sie tun können, eine Gleichheit testen.Als solche, Ihr timing Ergebnisse sind wahrscheinlich aufgrund anderer Prozesse auf Ihrem system ausgeführt werden; Sie gemessen Wand-Uhr-Zeit, und nicht deaktivieren Python garbage collection, noch haben Sie immer wieder testen Sie die gleiche Sache.
Versuchen, führen Sie Ihren test mit dem
timeit
- Modul, mit einem Wert vonnumbers
und man nicht in der Gruppe:Dies wiederholt sich jeden test 1 Millionen mal produziert:
Den Grund für die zwei unterschiedlichen Datentypen ist nicht für die Leistung, es ist funktional. Da frozensets sind unveränderlich, Sie können verwendet werden als Schlüssel in dictionaries. Sets können nicht für diesen Zweck verwendet werden.