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 und set 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.

InformationsquelleAutor Sven Hager | 2016-04-11
Schreibe einen Kommentar