2010-07-15 7 views
7

Tengo un método simple que devuelve un Nullable Int32 de un DataReader en lugar de un GetInt32 incorporado.C# Ganancia de rendimiento que devuelve un tipo anulable desde un SqlDataReader

Estoy llamando a este método muchas veces y tengo una situación en la que cualquier momento en que pueda afeitarme sería beneficioso.

¿Alguien puede sugerir alguna forma alternativa y más rápida de obtener un Int32 nullable del DataReader?

private Int32? GetNullableInt32(SqlDataReader dataReader, int fieldIndex) 
{ 
    return !dataReader.IsDBNull(fieldIndex) ? 
       dataReader.GetInt32(fieldIndex) : (Int32?)null; 
} 
+1

Creo que es casi tan bueno como lo que obtendrás. – LukeH

+0

Recuerdo haber leído que la comprobación de IsDBNull era lenta. Esto se ejecuta 5 millones de veces en aproximadamente 2 segundos. También tengo métodos similares para todos los otros tipos. Incluso una ganancia del 10% en este método reducirá el tiempo masivamente. –

+0

@Robin Day Primero buscaría primero otros factores de rendimiento: el porcentaje de ganancia frente al esfuerzo, argumentaría a este respecto, va a ser uno de los más bajos que vea. –

Respuesta

9

Me parece recordar que a veces puede por más rápido para obtener el valor como un objeto y luego verificar si eso es DBNull.

private Int32? GetNullableInt32(SqlDataReader dataReader, int fieldIndex) 
{ 
    object value = dataReader.GetValue(fieldIndex); 
    return value is DBNull ? (Int32?) null : (Int32) value; 
} 

Al menos vale la pena intentarlo. Tenga en cuenta que esto es asumiendo que puede unbox directamente a un int ... No estoy seguro si eso es correcto, pero será fácil de ver.

Ahora hay otro enfoque que es un poco menos seguro - que devolverá un valor nulo para cualquier valor no entero, incluso si el campo es en realidad una cadena, por ejemplo:

private Int32? GetNullableInt32(SqlDataReader dataReader, int fieldIndex) 
{ 
    return dataReader.GetValue(fieldIndex) as Int32?; 
} 

He escrito anteriormente acerca "como" con tipos anulables que no son tan rápidos como esperaba, pero este puede ser un caso ligeramente diferente ... una vez más, vale la pena intentarlo.

Sin embargo, me sorprendería mucho si esto es realmente un cuello de botella ... seguramente obtener los datos de la base de datos en primer lugar va a ser mucho más caro. ¿Tiene puntos de referencia para esto?

+0

Tengo puntos de referencia para esto, y sí, esta no es la parte más lenta de la llamada, sin embargo, he hecho todo lo posible para obtener los datos. vuelve más rápido y ahora solo buscas afeitarte los últimos dos segundos. Estoy ejecutando pruebas contra estos dos métodos ahora y publicaré los resultados. –

+0

+1 también es dudoso el cuello de botella: rara vez la red o la E/S superan una CPU. –

+0

En la creación de perfiles para 5 millones de llamadas en cada método. Mi método se ejecuta en 998ms Su primer método se ejecuta en 1169ms Su segundo método se ejecuta en 898ms ¡Eso es un 10% de ganancia y lo suficientemente bueno para mí! ¡Gracias! –

2

El código que desea optimizar (?:) será insignificante en comparación con la E/S circundante.

Por lo tanto, no va a ser más rápido.

+1

+1 de hecho, suena como una micro-optimización en el mejor de los casos, el OP también menciona en los comentarios que se ejecuta 5 millones de veces en 2 segundos ... suena lo suficientemente rápido para mí. –

Cuestiones relacionadas