2009-10-21 14 views
32

Sé que marcar los parámetros de cadena como const puede hacer una enorme diferencia en el rendimiento, pero ¿qué ocurre con los tipos ordinales? ¿Gano algo haciéndolos const?¿Hay alguna ventaja en usar parámetros const con un tipo ordinal?

Siempre he usado const parámetros al manipular cadenas, pero nunca para Integer, Pointer, instancias de clases, etc.

Al utilizar const A menudo tengo que crear variables temporales adicionales, que sustituyen a la ahora protegidos contra escritura parámetros, así que me pregunto: ¿gano algo al marcar los parámetros ordinales como const?

Respuesta

43

Necesita comprender la razón, para evitar la "programación de culto a la carga". Marcar cadenas como const hace una diferencia en el rendimiento porque ya no necesita usar un incremento entrelazado y decremento del refcount en la cadena, una operación que en realidad se vuelve más cara, no menos, con el paso del tiempo porque más núcleos significa más trabajo eso tiene que hacerse para mantener sincronizadas las operaciones atómicas. Esto es seguro ya que el compilador aplica la restricción "esta variable no cambiará".

Para los ordinales, que suelen ser de 4 bytes o menos, no hay ganancia de rendimiento. Con const, la optimización solo funciona cuando usa tipos de valores de más de 4 bytes, como matrices o registros, o tipos contados como cadenas e interfaces.

Sin embargo, hay otra ventaja importante: la legibilidad del código. Si pasa algo como const y no hace ninguna diferencia en absoluto al compilador, aún puede hacer una diferencia en , ya que puede leer el código y ver que la intención es que no se modifique. Eso puede ser significativo si no has visto el código antes (alguien más lo escribió) o si vuelves a él después de un largo tiempo y no recuerdas exactamente lo que estabas pensando cuando lo escribiste originalmente.

+0

+1 ciertamente una explicación más satisfactoria que la mía – jpfollenius

+13

Su primer párrafo es incorrecto con respecto a las cadenas. Las cadenas siempre pasan como su representación de puntero de cuatro bytes. 'Const' suprime el código en el prólogo y epílogo de la función que actualiza el recuento de referencias de la cadena. Lo mismo aplica para los parámetros de interfaz y las matrices dinámicas. Del mismo modo, los registros se pasan como punteros. 'Const' simplemente suprime el código de prólogo que copia el registro en la pila local de la función. En otras palabras, 'const' no tiene * efecto * en el lado * caller * de una función. Solo afecta al receptor de la llamada. –

+2

@Rob: Bummer que los comentarios no se pueden editar. Es fácil leer mal su comentario como si dijera que los registros siempre se pasan como punteros. –

8

declarar tipos ordinales const no hace ninguna diferencia porque se copian de todos modos (call-by-value), por lo que los cambios en la variable no afectan a la variable original.

procedure Foo (Val : Integer) 
begin 
Val := 2; 
end; 
... 
SomeVar := 3; 
Foo (SomeVar); 
Assert (SomeVar = 3); 

En mi humilde opinión declarar tipos ordinales const no tiene sentido y como dices requiere que introduzcas variables locales a menudo.

+2

Craig tiene un punto válido. Hay una buena razón para declarar un ordinal como const; simplemente no por razones de rendimiento. –

16

No puede accidentalmente tratarlos como var parámetros y tener su compilación de código. Entonces hace tus intenciones claras.

+3

Buen punto, pero ¿no es suficiente NO especificar un parámetro var para aclarar la intención? – jpfollenius

+2

Smasher, el compilador no distingue entre var y la convención predeterminada en lo que se le permite hacer con el argumento en el método. –

+1

Incluso si parece claro en este momento que se trata de un valor que no tiene la intención de cambiar, es posible que no lo haga seis meses más tarde cuando regrese a él, o cuando un programador de mantenimiento tenga que revisar su código. –

1

Depende de qué tan compleja es su rutina y cómo se usa. Si se usa en muchos lugares y requiere que el valor permanezca igual, declarelo como "const" para que sea despejado y seguro. Para el tipo de cadena, había un error (para Delphi 7 cuando toco) que causa daños en la memoria si se declara como "const".A continuación se muestra códigos de muestra

type 
    TFoo = class 
    private 
    FStr: string; 
    public 
    procedure DoFoo(const AStr: string); 
    begin 
     FStr := AStr; //the trouble code 1 
     ...... 
    end; 
    procedure DoFoo2; 
    begin 
     ..... 
     DoFoo(FStr); //the trouble code 2 
    end; 
    end; 
0

Hay una gran mejora en la velocidad usando Const con cuerdas:

function test(k: string): string; 
begin 
    Result := k; 
end; 

function test2(Const k: string): string; 
begin 
    Result := k; 
end; 

function test3(Var k: string): string; 
begin 
    Result := k; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
Var a: Integer; 
    s,b: string; 
    x: Int64; 
begin 
    s := 'jkdfjklf lkjj3i2ej39ijkl jkl2eje23 io3je32 e832 eu283 89389e3jio3 j938j 839 d983j9'; 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('default: '+x.ToString); 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test2(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('const: '+x.ToString); 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test3(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('var: '+x.ToString); 
end; 

por defecto: 443 const: 320 var: 325

por defecto: 444 const: 303 var : 310

predeterminado: 444 const: 302 var: 305

Lo mismo pasa con los números enteros:

por defecto: 142 const: 13 var: 14

Curiosamente, sin embargo, en 64 bits parece que hay casi ninguna diferencia con las cadenas (modo por defecto es solamente un poco más lenta que Const):

defecto: 352 const: 313 var: 314

Cuestiones relacionadas