Question

Je connais bien les différentes manières de traiter le texte d'analyse pour en savoir plus. Pour l'analyse de nombres entiers, par exemple, quel type de performance peut être attendu. Je me demande si quelqu'un connaît de bonnes statistiques à ce sujet. Je suis à la recherche de vrais chiffres de la part de quelqu'un qui a testé cela.

Laquelle de celles-ci offre la meilleure performance dans quelles situations?

Parse(...)  // Crash if the case is extremely rare .0001%

If (SomethingIsValid) // Check the value before parsing
    Parse(...)

TryParse(...) // Using TryParse

try
{
    Parse(...)
}
catch
{
    // Catch any thrown exceptions
}
Était-ce utile?

La solution

Utilisez toujours T.TryParse (chaîne de caractères, valeur T) . Lancer des exceptions coûte cher et devrait être évité si vous pouvez gérer la situation a priori . Utilisation d'un bloc try-catch pour "enregistrer" sur les performances (car votre débit de données non valide est faible) est un abus de la gestion des exceptions au détriment de la maintenabilité et des bonnes pratiques de codage. Suivez les bonnes pratiques de développement de l’ingénierie logicielle, rédigez vos scénarios de test, exécutez votre application, THEN benchmark et optimisez.

  

"Nous devrions oublier les petites économies, disons environ 97% du temps: l'optimisation prématurée est la racine de tous les maux . Pourtant, nous ne devrions pas laisser passer nos opportunités dans ce domaine critique de 3% " -Donald Knuth

Par conséquent, vous indiquez, comme dans les crédits carbone, que les performances de try-catch sont pires et que les performances de TryParse sont meilleures . Ce n'est qu'après avoir exécuté notre application et déterminé que nous avons une sorte de ralentissement w.r.t. L’analyse des chaînes envisagerait-elle d’utiliser autre chose que TryParse.

(éditer: étant donné que l'interrogateur a voulu que les données de synchronisation soient accompagnées de bons conseils, voici les données de synchronisation demandées)

Temps pour divers taux d'échec sur 10 000 entrées de l'utilisateur (pour les non-croyants):

Failure Rate      Try-Catch          TryParse        Slowdown
  0%           00:00:00.0131758   00:00:00.0120421      0.1
 10%           00:00:00.1540251   00:00:00.0087699     16.6
 20%           00:00:00.2833266   00:00:00.0105229     25.9
 30%           00:00:00.4462866   00:00:00.0091487     47.8
 40%           00:00:00.6951060   00:00:00.0108980     62.8
 50%           00:00:00.7567745   00:00:00.0087065     85.9
 60%           00:00:00.7090449   00:00:00.0083365     84.1
 70%           00:00:00.8179365   00:00:00.0088809     91.1
 80%           00:00:00.9468898   00:00:00.0088562    105.9
 90%           00:00:01.0411393   00:00:00.0081040    127.5
100%           00:00:01.1488157   00:00:00.0078877    144.6


/// <param name="errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryCatch(double errorRate, int seed, int count)
{
    Stopwatch stopwatch = new Stopwatch();
    Random random = new Random(seed);
    string bad_prefix = @"X";

    stopwatch.Start();
    for(int ii = 0; ii < count; ++ii)
    {
        string input = random.Next().ToString();
        if (random.NextDouble() < errorRate)
        {
           input = bad_prefix + input;
        }

        int value = 0;
        try
        {
            value = Int32.Parse(input);
        }
        catch(FormatException)
        {
            value = -1; // we would do something here with a logger perhaps
        }
    }
    stopwatch.Stop();

    return stopwatch.Elapsed;
}

/// <param name="errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryParse(double errorRate, int seed, int count)
{
    Stopwatch stopwatch = new Stopwatch();
    Random random = new Random(seed);
    string bad_prefix = @"X";

    stopwatch.Start();
    for(int ii = 0; ii < count; ++ii)
    {
        string input = random.Next().ToString();
        if (random.NextDouble() < errorRate)
        {
           input = bad_prefix + input;
        }

        int value = 0;
        if (!Int32.TryParse(input, out value))
        {
            value = -1; // we would do something here with a logger perhaps
        }
    }
    stopwatch.Stop();

    return stopwatch.Elapsed;
}

public static void TimeStringParse()
{
    double errorRate = 0.1; // 10% of the time our users mess up
    int count = 10000; // 10000 entries by a user

    TimeSpan trycatch = TimeTryCatch(errorRate, 1, count);
    TimeSpan tryparse = TimeTryParse(errorRate, 1, count);

    Console.WriteLine("trycatch: {0}", trycatch);
    Console.WriteLine("tryparse: {0}", tryparse);
}

Autres conseils

Bien que je n'ai pas personnellement décrit les différentes manières, ce chapitre a:

http://blogs.msdn.com/ianhu /archive/2005/12/19/505702.aspx

Try-Catch sera toujours le plus lent. TryParse sera plus rapide.

Les valeurs IF et TryParse sont identiques.

Voici un autre représentant des différences de performances , et le fait avec quelques types de données différents pour voir combien (le cas échéant) ils affectent de manière inhérente les performances: int, bool et DateTime.

Option 1: Will throw an exception on bad data.
Option 2: SomethingIsValid() could be quite expensive - particularly if you are pre-checking a string for Integer parsability.
Option 3: I like this.  You need a null check afterwards, but it's pretty cheap.
Option 4 is definitely the worst.

La gestion des exceptions est relativement coûteuse, évitez-la donc si vous le pouvez.

En particulier, il faut s'attendre à des entrées incorrectes et non exceptionnelles, vous ne devez donc pas les utiliser pour cette situation.

(Bien qu'avant TryParse, c'était peut-être la meilleure option.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top