it-swarm.com.de

Welches ist der schnellste STL-Container für find?

Als Vorwort in Ordnung, ich muss eine relativ kleine Teilmenge selten modifizierter Daten zwischenspeichern, um zu vermeiden, dass die Datenbank aus Performance-Gründen so häufig abgefragt wird. Diese Daten werden im reinen Lesezugriff stark verwendet, da sie häufig von einem viel größeren Datensatz in anderen Tabellen referenziert werden.

Ich habe eine Klasse geschrieben, die die Fähigkeit hat, im Wesentlichen die Gesamtheit der beiden fraglichen Tabellen im Speicher zu speichern, während sie auf Commit-Änderungen in Verbindung mit einem sicheren Thread-Rückrufmechanismus zum Aktualisieren der zwischengespeicherten Objekte achtet.

Meine aktuelle Implementierung enthält zwei std::vectors-Elemente für die Elemente jeder Tabelle. Die Klasse bietet sowohl Zugriff auf die Gesamtheit jedes Vektors als auch bequeme Methoden für die Suche nach einem bestimmten Element von Tabellendaten über std::find, std::find_if usw.

Weiß jemand, ob die Verwendung von std::list, std::set oder std::map über std::vector für die Suche vorzuziehen ist? Dies wird meistens von diesen Containern angefordert, wenn sie einmal aus der Datenbank ausgefüllt werden, wenn eine neue Verbindung hergestellt wird.

Ich bin auch offen für die Verwendung von C++ 0x-Features, die von VS2010 oder Boost unterstützt werden.

31
AJG85

Für die Suche nach einem bestimmten Wert benötigt es mit std::set und std::map O (log N) Zeit, während mit den anderen beiden O(N) Zeit benötigt wird; Also, std::set oder std::map sind wahrscheinlich besser. Da Sie Zugriff auf C++ 0x haben, können Sie auch std::unordered_set oder std::unordered_map verwenden, was durchschnittlich konstante Zeit in Anspruch nimmt.

Für find_if gibt es wenig Unterschiede, da es ein beliebiges Prädikat erfordert und Container natürlich nicht beliebig optimiert werden können.

Wenn Sie jedoch find_if häufig mit einem bestimmten Prädikat aufrufen, können Sie sich selbst optimieren: Verwenden Sie std::map oder std::set mit einem benutzerdefinierten Vergleicher oder Sondertasten und verwenden Sie stattdessen find.

52

Ein sortierter Vektor mit std::lower_bound kann genauso schnell sein wie std::set, wenn Sie nicht oft aktualisieren. Sie sind beide O (log n). Es lohnt sich, beide zu versuchen, um herauszufinden, was für Ihre eigene Situation besser ist.

21
Mark Ransom

Da Sie aus Ihren (erweiterten) Anforderungen nach mehreren Feldern suchen müssen, würde ich Sie auf Boost.MultiIndex verweisen.

Mit dieser Boost-Bibliothek können Sie one container (mit nur einem Beispiel für jedes enthaltene Element) erstellen und über eine beliebige Anzahl von Indizes indizieren. Außerdem können Sie genau festlegen, welche Indizes verwendet werden sollen.

Um die Art des zu verwendenden Index zu bestimmen, benötigen Sie umfangreiche Benchmarks. 500 ist eine relativ geringe Anzahl von Einträgen. Konstante Faktoren spielen daher keine gute Rolle. Darüber hinaus kann es einen merklichen Unterschied zwischen der Verwendung von Einzelthreads und Multithreads geben (die meisten Hashtabellenimplementierungen können bei Verwendung von MT kollabieren, da sie kein lineares Rehashing verwenden und somit ein einzelner Thread das Rebashing beendet Tabelle, alle anderen blockieren).

Ich würde einen sortierten Index empfehlen (überspringen, wenn möglich), um Bereichsanfragen (alle Namen, die mit Abc beginnen?) Rechnung zu tragen, wenn der Leistungsunterschied entweder nicht wahrgenommen wird oder einfach keine Rolle spielt.

3
Matthieu M.

Probier es aus. Es ist sehr einfach, Container sind in STL fast austauschbar. 

2
Piotr

Wenn Sie nur nach bestimmten Werten suchen möchten, einer bestimmten Spalte in der Tabelle, ist std::hash am schnellsten.

Wenn Sie mit mehreren verschiedenen Prädikaten suchen möchten, benötigen Sie eine Art Indexstruktur. Es kann implementiert werden, indem Sie Ihren aktuellen vektorbasierten Ansatz um mehrere Hashtabellen oder -karten erweitern, eine für jedes zu durchsuchende Feld, wobei der Wert entweder ein Index im Vektor oder ein direkter Zeiger auf das Element im Vektor ist.

Wenn Sie nach Bereichen suchen möchten, z. B. bei allen Ereignissen mit einem Datum im Juli, benötigen Sie eine geordnete Datenstruktur, in der Sie einen Bereich extrahieren können.

2
Anders Abel

Nicht stl, sondern ein handelsüblicher C++ - Container ist ein abax-Container, in dem O(1) gesucht, gelöscht, geändert und O(logn) eingefügt wird.

0
Jonathan Yue