J'ai un tampon de chaîne d'environ 2000 caractères et j'ai besoin de vérifier le tampon s'il contient une chaîne spécifique.
Effectuera la vérification dans une application Web ASP.NET 2.0 pour chaque requête en ligne.
Est-ce que quelqu'un sait si la méthode String.Contains donne de meilleurs résultats que méthode String.IndexOf ?
// 2000 characters in s1, search token in s2
string s1 = "Many characters. The quick brown fox jumps over the lazy dog";
string s2 = "fox";
bool b;
b = s1.Contains(s2);
int i;
i = s1.IndexOf(s2);
Contains
appelle IndexOf
:
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
Qui appelle CompareInfo.IndexOf
, Qui utilise finalement une implémentation CLR.
Si vous voulez voir comment les chaînes sont comparées dans le CLR cela vous le montrera (recherchez CaseInsensitiveCompHelper).
IndexOf(string)
n'a pas d'options et Contains()
utilise une comparaison ordinale (comparaison octet par octet plutôt que d'essayer d'effectuer une comparaison intelligente, par exemple, e avec é).
Donc, IndexOf
sera légèrement plus rapide (en théorie), car IndexOf
passe directement à une recherche de chaîne à l'aide de FindNLSString à partir de kernel32.dll (la puissance du réflecteur!).
Mis à jour pour .NET 4.0 - IndexOf n'utilise plus la comparaison ordinale et donc la méthode Contains peut être plus rapide. Voir le commentaire ci-dessous.
Probablement, cela n'aura aucune importance. Lisez ce post sur Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html
Contains (s2) est plusieurs fois (10 fois plus rapide sur mon ordinateur) plus rapide que IndexOf (s2) car Contains utilise StringComparison.Ordinal, qui est plus rapide que la recherche liée à la culture effectuée par IndexOf par défaut (mais cela peut changer dans .net 4.0 - http://davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx ).
Contains a exactement les mêmes performances que IndexOf (s2, StringComparison.Ordinal)> = 0 dans mes tests, mais il est plus court et clarifie votre intention.
Je gère un cas réel (contrairement à une référence synthétique)
if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) {
versus
if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) {
C'est une partie vitale de mon système et il est exécuté 131 953 fois (merci DotTrace).
Cependant surprise choquante, le résultat est l'inverse de celui attendu
: - /
net framework 4.0 (mis à jour comme pour le 13-02-2012)
En utilisant Reflector, vous pouvez voir que Contains est implémenté en utilisant IndexOf. Voici la mise en œuvre.
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
Donc, Contains est probablement un peu plus lent que d’appeler directement IndexOf, mais je doute que cela ait une signification pour les performances réelles.
Si vous voulez vraiment optimiser votre code micro, votre meilleure approche est toujours l'analyse comparative.
Le framework .net a une excellente implémentation de chronomètre - System.Diagnostics.Stopwatch
D'après une petite lecture, il apparaît que sous le capot, la méthode String.Contains appelle simplement String.IndexOf. La différence est String.Contains renvoie un booléen alors que String.IndexOf renvoie un entier avec (-1), indiquant que la sous-chaîne n'a pas été trouvée.
Je suggérerais d'écrire un petit test avec environ 100 000 itérations et de voir par vous-même. Si je devais deviner, je dirais que IndexOf est peut-être un peu plus rapide mais, comme je l'ai dit, c'est juste une supposition.
Jeff Atwood a un bon article sur les chaînes à son blog . C'est plus une question de concaténation mais peut être utile quand même.
Juste comme une mise à jour de ceci, j'ai fait quelques tests et fourni une chaîne de caractères assez longue, alors que Regex en parallèle est la méthode C # la plus rapide que j'ai trouvée (à condition que vous ayez plus d'un noyau, j'imagine)
Obtenir le nombre total de correspondances par exemple -
needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );
J'espère que cela t'aides!
Utilisez une bibliothèque de référence, comme cette récente incursion de Jon Skeet pour la mesurer.
Comme pour toutes les questions de (micro) performances, cela dépend des versions du logiciel que vous utilisez, des détails des données inspectées et du code entourant l'appel.
Comme pour toutes les questions de (micro) performances, la première étape consiste à obtenir une version en cours d’exécution facile à gérer. Ensuite, le benchmarking, le profilage et le réglage peuvent être appliqués aux goulots d'étranglement mesurés au lieu de deviner.