Pregunta

Do fuera parámetros en C # tiene ningún implicaciones de rendimiento que debería saber? (Como excepciones)

Es decir, ¿es una buena idea tener un método con un parámetro out en un bucle que se ejecutará un par de millones de veces por segundo?

Sé que es feo, pero lo estoy usando la misma manera que Int32.TryParse los está utilizando -. Devolviendo un bool decir si alguna validación se ha realizado correctamente y que posean parámetros out que contiene algunos datos adicionales si tuvo éxito

¿Fue útil?

Solución

Dudo que encontrará ninguna pérdida de rendimiento significativa a la utilización de un parámetro out. Hay que obtener información de vuelta a la persona que llama de una forma u otra - out es sólo una manera diferente de hacerlo. Usted puede encontrar que hay algunos penalización si se utiliza el parámetro a cabo ampliamente dentro del método, ya que puede significar también un nivel adicional de redirección para cada acceso. Sin embargo, no me esperaba que fuera significativo. Como es normal, escribir el código más legible y prueba si el rendimiento es ya lo suficientemente buena antes de tratar de optimizar aún más.

EDIT: El resto de esto es un aparte, de manera efectiva. Sólo es realmente relevante para los tipos de valores grandes, que por lo general se deben evitar todos modos:)

No estoy de acuerdo con la afirmación de Konrad sobre los "valores de retorno de todos los tipos> 32 bits se manejan similares o idénticos a los argumentos sobre el nivel de la máquina de todos modos" sin embargo. He aquí una pequeña aplicación de prueba:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

struct BigStruct
{
    public Guid guid1, guid2, guid3, guid4;
    public decimal dec1, dec2, dec3, dec4;
}

class Test
{
    const int Iterations = 100000000;

    static void Main()
    {
        decimal total = 0m;
        // JIT first
        ReturnValue();
        BigStruct tmp;
        OutParameter(out tmp);

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs = ReturnValue();
            total += bs.dec1;
        }
        sw.Stop();
        Console.WriteLine("Using return value: {0}",
                          sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs;
            OutParameter(out bs);
            total += bs.dec1;
        }
        Console.WriteLine("Using out parameter: {0}",
                          sw.ElapsedMilliseconds);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static BigStruct ReturnValue()
    {
        return new BigStruct();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void OutParameter(out BigStruct x)
    {
        x = new BigStruct();
    }
}

Resultados:

Using return value: 11316
Using out parameter: 7461

Básicamente mediante el uso de un parámetro de salida que estamos escribiendo los datos directamente al destino final, en lugar de escribirlo al marco de pila de la pequeña método y luego copiar de nuevo en el marco de pila del método Main.

No dude en criticar a la aplicación de referencia, aunque - que puede haber perdido algo

Otros consejos

No es un problema de rendimiento, sino algo que se le ocurrió antes - no se puede utilizar con la varianza en C # 4.0 .

Personalmente, tienden a usar parámetros out una buena cantidad en mi privado código (es decir, dentro de una clase, que tiene un método que devuelve valores múltiples sin necesidad de utilizar un tipo separado) - pero tienden a evitar ellos en la API pública, excepto por el patrón bool Try{Something}(out result).

No hay implicaciones de rendimiento. out es básicamente el mismo que cualquier viejo paso de argumentos, desde un punto de vista técnico. Si bien puede sonar plausible que amounds enormes de datos se copian (por ejemplo, para las grandes estructuras), esto es en realidad el mismo que para los valores de retorno.

De hecho, los valores de retorno para todos los tipos> 32 bits se manejan similar a out argumentos en la nivel de la máquina de todos modos.

Tenga en cuenta que la última afirmación no sugiere que devolver un valor de parámetro == out en .NET. punto de referencia de Jon muestra que esto es obviamente (y lamentablemente) no es el caso. De hecho, para que sea idéntico, valor de retorno llamado optimización se emplea en los compiladores de C ++. Algo similar potencialmente podría hacerse en futuras versiones del ECI para mejorar el rendimiento de volver estructuras de gran tamaño (sin embargo, ya que las estructuras grandes son bastante raros en .NET, esto podría ser una optimización innecesaria).

No obstante , (y con mi conocimiento muy limitado de montaje x 86), volviendo objetos de llamadas a funciones que generalmente implica la asignación de espacio suficiente en el lugar de llamada, empujando la dirección en la pila y llenándolo copiando el valor de retorno en ella. Este es básicamente el mismo que out hace, solamente omitiendo una copia temporal innecesaria del valor ya que la ubicación de memoria de destino se puede acceder directamente.

La razón principal para evitar cabo parámetros es la legibilidad del código, en lugar de rendimiento.

Para los tipos de valor que no hay diferencia real de todos modos (que siempre copia) y de los tipos de referencia que es básicamente el mismo que el que pasa por ref.

Nueve de cada diez veces que es mejor de la creación de su propia clase registro mudo, en lugar de utilizar un parámetro de salida -. Esto es más fácil de leer y entender cuando regresa al código más tarde

Sin parámetros se pasan por ref. Por lo que sólo pasa un puntero en la pila.

Si el tipo de valor es grande, hay menos copia, pero después hay que eliminar la referencia al puntero en cada uso variable.

El uso de un parámetro de salida no perjudicar el rendimiento. Un parámetro de salida es básicamente un parámetro de referencia, por lo tanto la persona que llama y el punto destinatario de la llamada a la misma pieza de memoria.

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