Der neue C++ Standard bringt neue, ungeordnete Container mit, für die sich eigene Hashfunktionen implementieren lassen, sofern man das möchte. Das habe ich mal ausprobiert und vier Hashfunktionen getestet und auch einen kleinen Benchmarktest dafür gemacht. Zum Einsatz kommen folgende Hashfunktionen:
Als Testgrundlage dient eine 600MB große Textdatei, die englische Wörter bis zur Wortlänge 20 zeilengetrennt beinhaltet. Diese wird dann durch Imbuing eingelesen und alle Wörter werden in eine unordered- Map eingefügt. Diese Wortliste (wordlist.txt) kann in Kürze auch hier heruntergeladen werden.
Es folgt nun die Implementation der drei Hashfunktionen:
Eine nicht wirklich gute Hashfunktion soll hier mal als "schlechtes" Beispiel dienen - die bad- Hashfunktion reduziert verschiedene Eingabewert auf den Hashwert, der der Länge des Eingabewertes entspricht. Somit belegen gleichlange Wörter immer ein und denselben Hashwert:
Die verybad- Hashfunktion reduziert verschiedene Eingabewerte auf nur EINEN Hashwert, das wird sich später auf ihre Performanz sehr stark auswirken!
Hier mal eine kleine, kurze Hashfunktion die ich mir schnell ausgedacht habe:
Nun wird gemessen, wie performant die einzelnen Hashfunktionen sind. Der Test erfolgt auf einem 32-bit System, Dual- Core Rechner. Als Eingabedatei dient wie oben erwähnt die wordlist.txt:
Es werden also ca. 116 Millionen Wörter eingelesen und in der unordered- Map gespeichert.
Der Jenkins- Hash tritt als erstes an. Es werden drei Durchläufe gemacht:
Erster Durchlauf:
Zweiter Durchlauf:
Dritter Durchlauf (schnellster):
Erster Durchlauf (schnellster):
Zweiter Durchlauf:
Dritter Durchlauf:
Nun tritt meine selbstgeschriebene Hashfunktion an.
Erster Durchlauf (schnellster):
Zweiter Durchlauf:
Dritter Durchlauf:
Da diese Funktion ziemlich unperformant ist, wurde nur ein Testlauf durchgeführt!
Durchlauf:
Da diese Funktion noch unperformanter ist, als die Bad- Hashfunktion, wurde hier ebenfalls nur ein Testlauf durchgeführt!
Durchlauf:
Die Jenkins- Hashfunktion kommt bei wide- String ziemlich nah an die Performanz der Standardhashfunktion der ungeordneten Container in C++ heran! Die beiden Funktionen trennen gerade mal 2 Sekunden. Etwas länger dauerte dann meine eigene Hashfunktion, die ca. 30 Sekunden mehr Zeit benötigt, als die Standardhashfunktion. Wirklich weit abgeschlagen die liegen beiden "bad-" Hashfunktionen. Zusammenfassend kann man sagen, dass die ungeordneten Container tolle neue Möglichkeiten bieten, eigene Hashfunktionen zum implementieren (spanned wird es mit eigenen Klassen dann) nur man kann auch sehr, sehr viel "falsch" machen!
Desweiteren bietet sich mit solchen großen Datenmengen auch wunderbar ein Vergleich von dem Durchlaufen solcher (ungeordneten) Containern an. Im nächsten Artikel werde ich einmal die Performanz von Iteratoren, Range- For und Boost For- Each vergleichen!
wordlist.txt: Rund 600 MB (!) groß, zeilengetrennte, englische Wörter (bis Wortlänge 20). Zu finden hier.
main.cpp: Das Hauptprogramm, welches alle Hashfunktionen implementiert und die wordlist.txt in die ungeordneten Container einliest. Zu finden hier.
Eine neue, aktualisierte Version dieses Artikels befindet sich hier!