web-dev-qa-db-fra.com

Quel est le conteneur STL le plus rapide à trouver?

D'accord, j'ai besoin de mettre en cache un sous-ensemble relativement petit de données rarement modifiées pour éviter d'interroger la base de données aussi fréquemment pour des raisons de performances. Ces données sont fortement utilisées en lecture seule, car elles sont souvent référencées par un ensemble de données beaucoup plus volumineux dans d'autres tables.

J'ai écrit une classe qui aura la capacité de stocker en mémoire la totalité des deux tables en question tout en écoutant les modifications de validation en conjonction avec un mécanisme de rappel sécurisé pour la mise à jour des objets en cache.

Mon implémentation actuelle a deux std::vectors un pour les éléments de chaque table. La classe fournit à la fois un accès à l'intégralité de chaque vecteur ainsi que des méthodes pratiques pour rechercher un élément spécifique de données de table via std::find, std::find_if, etc.

Est-ce que quelqu'un sait si utiliser std::list, std::set ou std::map au-dessus de std::vector serait préférable? La plupart du temps, c'est ce qui sera demandé à ces conteneurs après avoir été renseigné une fois à partir de la base de données lorsqu'une nouvelle connexion est établie.

Je suis également ouvert à l'utilisation des fonctionnalités C++ 0x prises en charge par VS2010 ou Boost.

31
AJG85

Pour rechercher une valeur particulière, avec std::set et std::map cela prend O (journal N), alors qu'avec les deux autres, cela prend O(N); Donc, std::set ou std::map sont probablement meilleurs. Puisque vous avez accès à C++ 0x, vous pouvez également utiliser std::unordered_set ou std::unordered_map qui prennent un temps constant en moyenne.

Pour find_if, il y a peu de différence entre eux, car il faut un prédicat arbitraire et les conteneurs ne peuvent pas optimiser de manière arbitraire, bien sûr.

Toutefois, si vous appelez fréquemment find_if avec un prédicat donné, vous pouvez optimiser vous-même: utilisez un std::map ou std::set avec un comparateur personnalisé ou des clés spéciales et utilisez plutôt find.

52

Un vecteur trié utilisant std::lower_bound peut être aussi rapide que std::set si vous ne mettez pas à jour très souvent. ils sont tous les deux O (log n). Cela vaut la peine d'essayer les deux pour voir ce qui convient le mieux à votre situation.

21
Mark Ransom

Étant donné que parmi vos exigences (étendues), vous devez effectuer des recherches dans plusieurs champs, je vous indiquerais Boost.MultiIndex.

Cette bibliothèque Boost vous permet de construire one container (avec un seul exemple de chaque élément qu’il contient) et de l’indexer sur un nombre arbitraire d’index. Il vous permet également de préciser les index à utiliser.

Pour déterminer le type d’indice à utiliser, vous aurez besoin de points de repère étendus. 500 est un nombre relativement faible d'entrées, donc les facteurs constants ne jouent pas bien. De plus, il peut y avoir une différence notable entre les utilisations à un seul thread et les multi-threads (la plupart des implémentations de table de hachage peuvent s’effondrer sur l’utilisation de MT car elles n’utilisent pas le rehachage linéaire, et ainsi un seul thread finit par réhase table, bloquant toutes les autres).

Je recommanderais un index trié (skip-list type, si possible) pour prendre en charge les demandes de plage (tous les noms commençant par Abc?) Si la différence de performances est soit imperceptible, soit simplement indifférente.

3
Matthieu M.

Essaye-le. C’est très simple, les conteneurs sont presque interchangeables en LIST. 

2
Piotr

Si vous souhaitez uniquement rechercher des valeurs distinctes, une colonne spécifique du tableau, std::hash est le plus rapide.

Si vous voulez pouvoir utiliser plusieurs prédicats différents, vous aurez besoin d'une sorte de structure d'index. Pour ce faire, vous pouvez étendre votre approche basée sur les vecteurs à l'aide de plusieurs tables de hachage ou cartes, une pour chaque champ à rechercher, où la valeur est un index dans le vecteur ou un pointeur direct sur l'élément du vecteur.

Pour aller plus loin, si vous voulez pouvoir rechercher des plages, telles que toutes les occasions ayant une date en juillet, vous avez besoin d'une structure de données ordonnée, où vous pouvez extraire une plage.

2
Anders Abel

Non stl, mais un conteneur commercial c ++ est un conteneur abax contenant O(1) dans les fonctions de recherche, suppression, modification, O(logn).

0
Jonathan Yue