EDIT: Maintenant que vous avez fourni un peu plus de contexte:
Essayer de reproduire, je réussi à trouver un goulot d'étranglement dans string.Length
du tout. La seule façon de le rendre plus rapide était de commenter à la fois le test et le corps du bloc if - ce qui n'est pas vraiment juste. Le simple fait de commenter la condition a ralenti les choses, c'est-à-dire que la copie inconditionnelle de la référence était plus lente que la vérification de la condition. Comme nous l'avons souligné, l'utilisation de la surcharge string.Split
qui supprime les entrées vides pour vous est l'optimisation réelle du tueur.
Vous pouvez aller plus loin, en évitant de créer un nouveau tableau de char avec juste un espace à chaque fois. Vous allez toujours passer la même chose efficacement, alors pourquoi ne pas en profiter?
Les tableaux vides sont effectivement immuables. Vous pouvez optimiser le cas null/vide en retournant toujours la même chose.
Le code optimisé devient:
private static readonly char[] Delimiters = " ".ToCharArray();
private static readonly string[] EmptyArray = new string[0];
public static string[] SplitOnMultiSpaces(string text)
{
if (string.IsNullOrEmpty(text))
{
return EmptyArray;
}
return text.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries);
}
String.Length
ne fait absolument pas compter les lettres dans la chaîne. La valeur est stockée sous la forme d'un champ - bien que je semble me souvenir que le bit supérieur de ce champ est utilisé pour se rappeler si tous les caractères sont ASCII (ou utilisés de toute façon) pour activer d'autres optimisations. Donc l'accès à la propriété peut avoir besoin de faire un bitmask, mais ce sera toujours O (1) et je m'attendrais à ce que le JIT l'insère aussi. (Il est mis en œuvre comme extern
, mais nous espérons que n'affecterait pas le JIT dans ce cas -. Je pense qu'il est assez opération potentiellement avoir un soutien spécial commun)
Si vous savez déjà que la chaîne est non nulle, alors votre test existant de
if (s.Length != 0)
est la meilleure façon de procéder si vous êtes à la recherche de performances brutes IMO. Personnellement, dans la plupart des cas j'écrire:
if (s != "")
pour le rendre plus clair que nous ne sommes pas tellement intéressés par la longueur en tant que valeur si c'est la chaîne vide. Ce sera légèrement plus lent que le test de longueur, mais je crois que c'est plus clair. Comme toujours, j'irais chercher le code le plus clair jusqu'à ce que vous ayez des données de benchmark/profiling pour indiquer que c'est vraiment un goulot d'étranglement. Je sais que votre question concerne explicitement la recherche du test le plus efficace, mais je pensais que je le mentionnerais de toute façon. Avez-vous des preuves que ce est un goulot d'étranglement?
EDIT: Juste pour donner plus claires raisons de ma suggestion de pas à l'aide string.IsNullOrEmpty
: un appel à cette méthode me suggère que l'appelant tente explicitement de traiter le cas où la variable est nulle, sinon ils n » Je l'ai mentionné. Si à ce point du code il compte comme un bogue si la variable est null, alors vous ne devriez pas essayer de le gérer comme un cas normal.
Dans ce cas, le chèque est en fait Length
mieux d'une manière que le test de l'inégalité que je l'ai suggéré: il agit comme une affirmation implicite que la variable est non nulle. Si vous avez un bug et que est null, le test va lancer une exception et le bug sera détecté tôt. Si vous utilisez le test d'égalité, il traitera null comme étant différent de la chaîne vide, il ira donc dans le corps de votre instruction "if". Si vous utilisez string.IsNullOrEmpty
, la valeur null sera considérée comme étant vide, de sorte qu'elle ne sera pas incluse dans le bloc.
Le problème de perf vous faites face est très probablement résolu un autre! Avez-vous profilé et constaté que le goulot d'étranglement est vraiment là? –
Par curiosité, quelle version du framework ciblez-vous? –
** NOTE ** pour d'autres seraient-être-answerers: d'Eric a publié une réponse qui clarifie sa question (un peu) ci-dessous .... –