Pregunta

Sé mucho sobre las diferentes formas de manejar el análisis de texto para obtener información. Para analizar enteros, por ejemplo, qué tipo de rendimiento se puede esperar. Me pregunto si alguien sabe de alguna buena estadística sobre esto. Estoy buscando algunos números reales de alguien que haya probado esto.

¿Cuál de estos ofrece el mejor rendimiento en qué situaciones?

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
}
¿Fue útil?

Solución

Utilice siempre T. TryParse (string str, out T value) . Lanzar excepciones es costoso y debe evitarse si puede manejar la situación a priori . Usando un bloque try-catch para " guardar " en el rendimiento (porque su velocidad de datos no válida es baja) es un abuso del manejo de excepciones a expensas de la mantenibilidad y las buenas prácticas de codificación. Siga las prácticas sólidas de desarrollo de ingeniería de software, escriba sus casos de prueba, ejecute su aplicación, ENTONCES compare y optimice.

  

" Deberíamos olvidarnos de las pequeñas eficiencias, digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal . Sin embargo, no debemos dejar pasar nuestras oportunidades en ese crítico 3% " -Donald Knuth

Por lo tanto, usted asigna, arbitrariamente, como en los créditos de carbono, que el rendimiento de try-catch es peor y que el rendimiento de TryParse es mejor . Solo después de ejecutar nuestra aplicación y determinar que tenemos algún tipo de desaceleración w.r.t. análisis de cadenas incluso consideraríamos usar algo que no sea TryParse.

(editar: dado que parece que el interlocutor quería que los datos de tiempo fueran con buenos consejos, aquí están los datos de tiempo solicitados)

Tiempos para varias tasas de falla en 10,000 entradas del usuario (para los no creyentes):

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);
}

Otros consejos

Aunque no he perfilado personalmente las diferentes formas, este capítulo tiene:

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

Try-Catch siempre será el más lento. TryParse será más rápido.

El IF y TryParse son iguales.

Aquí está otro tipo que también ha perfilado las diferencias de rendimiento , y lo hace con algunos tipos de datos diferentes para ver cuánto (si es que lo hacen) afectan inherentemente el rendimiento: int, bool y 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.

El manejo de excepciones es relativamente costoso, así que evítelo si puede.

En particular, se esperan entradas malas, no excepcionales, por lo que no debe usarlas para esta situación.

(Aunque, antes de TryParse, puede haber sido la mejor opción.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top