2009-09-14 5 views
2

J'ai un peu de code qui sera exécuté beaucoup à une partie, et je me demande comment procéder pour une implémentation plus efficace. Je vais utiliser une boucle pour simuler la partie la est exécuté beaucoup:Une comparaison de chaînes ou une recherche de hachage est-elle plus rapide en Perl?

option A:

my %sections = (
    'somestring1' => 1, 
    'somestring2' => 1, 
    'somestring3' => 1, 
    'somestring4' => 1 
); 

for (0..10000) 
{ 
    # $element is chosen at random 
    $namespace = $element if $sections{$element}; 
} 
Option

B:

for (0..10000) 
{ 
    # $element is chosen at random 
    $namespace = $element if ($element eq'somestring1' || 
          $element eq'somestring2' || 
          $element eq'somestring3' || 
          $element eq'somestring4'); 
} 

référence Quelqu'un peut-il ceci ou connaître la réponse que je suis pas familier avec les outils d'analyse comparative.

Ce code n'a probablement pas de sens dans ce contexte mais c'est en fait ce que j'ai besoin d'utiliser.

+2

Commencez par le faire tourner, puis faites le rapidement. –

Répondre

17

Utilisez la fonction cmpthese à partir du module Benchmark

use strict; 
use warnings; 
use Benchmark qw'cmpthese'; 

my %sections = (
    somestring1 => 1, 
    somestring2 => 1, 
    somestring3 => 1, 
    somestring4 => 1 
); 

my @elements = map { 'somestring' . int(1 + rand(10)) } 1 .. 100; 

my $namespace; 

cmpthese(100000, { 
    hash_value => sub { 
     foreach my $element (@elements) { 
      $namespace = $element if $sections{$element}; 
     } 
    }, 
    hash_exists => sub { 
     foreach my $element (@elements) { 
      $namespace = $element if exists $sections{$element}; 
     } 
    }, 
    string_cmp => sub { 
     foreach my $element (@elements) { 
      $namespace = $element if (
       $element eq'somestring1' || 
       $element eq'somestring2' || 
       $element eq'somestring3' || 
       $element eq'somestring4'); 
     } 
    }, 
}); 

Mes résultats (en cours d'exécution Perl 5.10 sur Windows XP):

   Rate string_cmp hash_value hash_exists 
string_cmp 18932/s   --  -44%  -50% 
hash_value 33512/s   77%   --  -12% 
hash_exists 38095/s  101%   14%   -- 

Ainsi, une recherche de hachage est 77% plus rapide que les comparaisons de chaînes en cascade et vérifier l'existence de hash au lieu de la valeur (comme Adam Bellaire l'a suggéré) est encore 14% plus rapide.

+0

J'ai un mauvais pressentiment, mais je serais curieux de voir comment les tests sur l'expression rationnelle '/^somestring [1234] $ /' se compareraient à ces trois méthodes. Je m'attends à ce que ça ne soit pas aussi rapide que "existe" mais j'aimerais voir comment ça se compare à la comparaison de chaînes. –

+0

Je montre que '/^somestring [1234] $ /' est environ 3% plus lent que les comparaisons de chaînes, bien que les performances du monde réel dépendent fortement du nombre de clés et du motif (le cas échéant) dans leurs valeurs. –

+1

<3 Michael Carman ... donne un poisson à un homme ... enseigne à un homme à pêcher ... etc – mikegrb

4

Le mécanisme de recherche de hachage est considérablement plus rapide.

5

Ma conjecture est que la première version, avec exists va être plus rapide, pour ne pas mentionner plus lisible et maintenable.

for (0..10000) 
{ 
    # $element is chosen at random 
    $namespace = $element if exists $sections{$element}; 
} 

une simple vérification de l'existence d'une clé de hachage est plus rapide que la récupération de sa valeur de comparaison, utilisez donc exists.

3

Il est probablement temps de se familiariser avec les outils d'analyse comparative, comme le module CPAN Benchmark.

+0

Ceci est vrai, cependant si le hachage devient très grand, je ne peux pas imaginer préconiser l'incorporation des valeurs dans une expression booléenne géante pour des raisons de performance. –

+0

Vous avez raison, ce qui signifie que j'ai mal compris la question .. Je pensais que le PO voulait vérifier si la clé était dans un * sous-ensemble * de toutes les clés dans le hachage, plutôt que dans le hachage lui-même. Correction de la réponse :) – Ether

0

Le benchmark de Michael Carman est sympa, mais les résultats sont assez vieux maintenant, donc les gens qui ne l'utilisent pas sur leur propre machine pourraient se faire une idée fausse. Ainsi, la même référence exacte (seulement 10x plus de cas pour donner des résultats plus cohérents) sur un Mac Pro w/Mac OS X et Perl 5.24.1:

   Rate string_cmp hash_exists hash_value 
string_cmp 54142/s   --  -28%  -32% 
hash_exists 74850/s   38%   --   -7% 
hash_value 80192/s   48%   7%   -- 

Cependant, sur une AWS avec CentOS 7/Perl 5.24.0 nous obtenons:

string_cmp 70373/s   --  -24%  -25% 
hash_value 92851/s   32%   --   -1% 
hash_exists 93545/s   33%   1%   -- 

donc, je dirais tester votre propre machine, mais existe ne semble pas offrir un avantage actuellement (sur mon Mac avec le dernier Perl, il est encore plus lent dans ce mesurablement test spécifique - et même sur d'autres tests). Une chose que je n'aime pas à propos de l'indice de référence est qu'il choisit plutôt arbitrairement de comparer 4 égalités avec un test de hachage. Ne pas confondre, si nous avons seulement un élément dans le hachage, donc on compare avec une seule égalité que nous obtenons (sur mon Mac Pro/Perl 5.24.1):

hash_value 119474/s   --   -1%  -14%  -34% 
hash_exists 121065/s   1%   --  -12%  -33% 
grep  138122/s   16%   14%   --  -23% 
string_cmp 180180/s   51%   49%   30%   -- 

j'ai jeté là-dedans une seule grep qui évite la boucle foreach pour la comparaison.Ainsi, une seule égalité est évidemment plus rapide qu'un chèque de hachage, mais pas deux fois plus vite, donc si vous pouvez remplacer seulement deux égalités avec un hachage vérifier que vous obtenez un avantage:

string_cmp 104167/s   --  -15%  -17% 
hash_value 121951/s   17%   --   -2% 
hash_exists 125000/s   20%   2%   -- 

Cependant, ceci est le pré de hachage - Construit en dehors de la boucle comme dans l'exemple original. Et si nous créons le hachage sur chaque cycle de référence? C'est à dire. vous avez quelques valeurs que vous voulez vérifier pour l'existence dans un tableau, est la surcharge de la création d'un hachage avec eux en vaut la peine? Je ne vais pas vous ennuyer avec plus de résultats puisque vous pourriez trouver qu'ils sont différents sur votre machine, mais la réponse est que pour 2 valeurs "ça dépend" (donc peut-être vous ne devriez pas déranger), mais pour 3 ou plus vous devriez faire il.