Ja, TFPDataHashTable und TFPHashList sind nur in spezifischen Situationen nützlich, aber dann ist TFPHashList gut.Warf hat geschrieben: Cooler Benchmark, aber man muss natürlich auch beachten das TFPDataHashTable und TFPHashList nur pointer als value erlauben. Klar kann man unter x86_64 CPUs auch integer rein schieben, ist aber nicht portable, wirft ne warning und ist, wenn ich das mal so sagen darf, kein sauberer Stil. Um also was anderes als TObjects reinzuschieben, muss man indirection verwenden, was bei TFPGMap oder gHashMap.THashMap nicht der Fall ist. Das kann die benchmarks natürlich beinflussen.
Die nicht generischen haben aber auch den Vorteil, dass das Programm klein bleibt, statt für jeden Typ den Mapcode neuzugenerieren. Letztendlich unterscheiden sich die Values nur nach Größe und Referenzcounting. Wenn FPC nun schlau kompiliert, könnte es alle 8-Byte Werte (pointer/TObject/int64/...) zusammenmergen und den Assemblercode für die alle nur einmal ausgeben. Ich bezweifel, dass FPC so schlau ist, deshalb verwende ich eine generic-pointer-generic Konstruktion. Ausgehend von einer generischen Map, wird die dann mit pointer Value specialized, und dann kommt eine generische Wrappermapklasse darum, die den Wert zu pointer cast. Das geht selbst mit string, da wird der string zu pointer gecastet und nur die Wrapperklasse aktualisert den Referenzzähler beim Einfügen/Löschen. Das hilft auch bei schlecht programmierten Maps, die womöglich intern Kopien von den Werten machen. Wenn die bei String den Referenzzähler ändert würden, macht das die Performance kaputt
Ja das geht auch bei den meisten Maps. Nur muss man sich dann vermutlich noch eine eigene Hashfunktion bauen.Warf hat geschrieben: Das nächste ist das keys natürlich mehr als strings sein können. Einen nicht string erst mal zu string serialisieren um dann den lookup zu machen beeinflusst natürlich auch die Zugriffszeit, besonders bei komplexeren datentypen wie records.
Das macht bei der Implementierung auch Probleme. Da hatte ich eine Map, die nicht funktioniert hat, weil die String/Nicht-String Unterscheidung falsch implementiert war. Und die avk Maps verwenden für die Unterscheidung eine Funktion, die es nur ab FPC 3.2 gibt.
Dann könnte man auch Typen mischen, zum Beispiel String einfügen und als pchar mit Länge auslesen.
Das wäre interessant. Sollte mal jemand messen (mein benchmark ist auch open-source), aber dafür habe ich keine Zeit mehr. Das ist auch mehr Aufwand als einfügen/auslesen, weil sich das bei den Maps mehr unterscheidet.Warf hat geschrieben: Und natürlich ist es auch eine frage was man damit macht. Z.b. wäre es auch interessant wie hoch die geschwindigkeit beim löschen von elementen und drüber iterieren ist. Ich würde vermuten das das drüber iterieren bei TFPGMap deutlich schneller sein sollte als bei den HashMap counterparts.
Hashmaps können aber auch schnell iterieren, das hängt davon ab, wie die implementiert sind. Ich habe lange Zeit Bero's FLRE Map verwendet (weil ich sein FLRE sowieso schon für reguläre Ausdrücken verwende und dann keine zusätzliche Library brauche), die speichert alle Key/Wert Daten ganz normal hintereinander in einem Array. Die Hashmap ist dann ein zusätzliches Array, dass für den Hashcode lediglich den Index im Array speichert. Da ist das iterieren optimal.
Zumindest solange nichts gelöscht wird. Löschen ist da ganz blöd, die verwendet ein drittes Array, um zu speichern welche Indizes gelöscht wurden. Die gelöschten Indizes werden dann im Key/Wert-Array nicht mehr verwendet, bis zum nächsten Rehashing.
Das klingt nach einer schlechten Implementierung, doch es läuft schneller als jede FPC Map.
rtl generics sind auch Standardbibliotheken. Vielleicht sogar die einzigen, die echte Pascal Standardbibliotheken sind, weil sie auch Delphi kompatibel sein sollen.Warf hat geschrieben: Das gesagt ist so eine übersicht natürlich schon cool. Vor allem weil du auch nicht standard bibliotheken drin hast. Denn TFPDataHashTable und TFPHashList wegen der "string-pointer" zuweisung m.M.n. keine wirkliche alternative darstellt (allein die tatsache das man das Memory-Management für die daten übernhemen muss), sehen die alternativen in den Standardbibliotheken eher mau aus. TFPGMap, gmap.TMap und ghashmap.THashMap sind so wie ich das sehe da die einzigen Optionen die standardmäßig verfügbar sind.