Optimización de alternativas a DateTime.Now

Resuelto Dan Tao asked hace 15 años • 4 respuestas

Un colega y yo estamos discutiendo este tema y espero obtener algunas opiniones externas sobre si la solución que propongo es o no una buena idea.

Primero, un descargo de responsabilidad: me doy cuenta de que la noción de "optimizar DateTime.Now" les parece una locura a algunos de ustedes. Tengo un par de defensas preventivas:

  1. A veces sospecho que aquellas personas que siempre dicen: "Las computadoras son rápidas; la legibilidad siempre viene antes que la optimización" a menudo hablan desde su experiencia en el desarrollo de aplicaciones donde el rendimiento, aunque puede ser importante , no lo es . Me refiero a la necesidad de que las cosas sucedan lo más instantáneamente posible, es decir, en nanosegundos (en ciertas industrias, esto importa, por ejemplo, el comercio de alta frecuencia en tiempo real).
  2. Incluso teniendo esto en cuenta, el enfoque alternativo que describo a continuación es, de hecho, bastante legible. No es un truco extraño, sólo un método simple que funciona de manera confiable y rápida.
  3. Hemos realizado pruebas. DateTime.Now es lento (relativamente hablando). El método siguiente es más rápido.

Ahora, pasemos a la pregunta en sí.

Básicamente, a partir de las pruebas, descubrimos que DateTime.Nowse necesitan aproximadamente 25 tics (alrededor de 2,5 microsegundos) para ejecutarse. Por supuesto, esto se promedia entre miles y millones de llamadas. Parece que la primera llamada en realidad lleva una cantidad significativa de tiempo y las llamadas posteriores son mucho más rápidas. Pero aun así, 25 ticks es el promedio.

Sin embargo, mi colega y yo notamos que DateTime.UtcNowlleva mucho menos tiempo ejecutarlo: en promedio, apenas 0,03 microsegundos.

Dado que nuestra aplicación nunca se ejecutará mientras haya un cambio en el horario de verano , mi sugerencia fue crear la siguiente clase:

public static class FastDateTime {
    public static TimeSpan LocalUtcOffset { get; private set; }

    public static DateTime Now {
        get { return DateTime.UtcNow + LocalUtcOffset; }
    }

    static FastDateTime() {
        LocalUtcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
    }
}

En otras palabras, determine el desplazamiento UTC para la zona horaria local una vez (al inicio) y desde ese momento en adelante aproveche la velocidad de DateTime.UtcNowpara obtener la hora actual mucho más rápido a través de FastDateTime.Now.

Podría ver que esto sería un problema si el desplazamiento UTC cambiara durante el tiempo que se estaba ejecutando la aplicación (si, por ejemplo, la aplicación se estaba ejecutando durante la noche); pero como ya dije, en nuestro caso eso no sucederá.

Mi colega tiene una idea diferente sobre cómo hacerlo, lo cual es demasiado complicado para que yo lo explique aquí. En última instancia, hasta donde puedo decir , ambos enfoques arrojan un resultado preciso, siendo el mío un poco más rápido (~0,07 microsegundos frente a ~0,21 microsegundos).

Lo que quiero saber es:

  1. ¿Me estoy perdiendo de algo? Dado el hecho mencionado anteriormente de que la aplicación sólo se ejecutará dentro del plazo de una sola fecha, ¿es FastDateTime.Nowsegura?
  2. ¿ Alguien más puede pensar en una forma aún más rápida de obtener la hora actual?
Dan Tao avatar Oct 14 '09 00:10 Dan Tao
Aceptado

¿Podría simplemente usar DateTime.UtcNow y convertir solo a la hora local cuando se presenten los datos? Ya ha determinado que DateTime.UtcNow es mucho más rápido y eliminará cualquier ambigüedad en torno al horario de verano.

 avatar Oct 13 '2009 17:10

Una diferencia entre el resultado de

DateTime.Now

y

DateTime.UtcNow + LocalUtcOffset 

es el valor de la propiedad Kind: Local vs Utc respectivamente. Si el DateTime resultante se pasa a una biblioteca de terceros, considere devolverlo

DateTime.SpecifyKind(DateTime.UtcNow + LocalUtcOffset, DateTimeKind.Local)
 avatar Jun 22 '2010 18:06

Me gusta tu solución. Hice algunas pruebas para ver cuánto más rápido es en comparación con el normal.DateTime.Now

DateTime.UtcNowes 117 veces más rápido queDateTime.Now

Usar DateTime.UtcNowes suficientemente bueno si sólo nos interesa la duración y no el tiempo en sí. Si todo lo que necesitamos es calcular la duración de una sección de código específica (hacer duration= End_time - Start_time), entonces la zona horaria no es importante y DateTime.UtcNowes suficiente.

Pero si necesitamos el tiempo mismo, entonces debemos hacerlo. DateTime.UtcNow + LocalUtcOffset

Simplemente agregando el lapso de tiempo se ralentiza un poco y ahora, según mis pruebas, somos solo 49 veces más rápidos que el normal.DateTime.Now

Si ponemos este cálculo en una función/clase separada como se sugiere, llamar al método nos ralentiza aún más y solo somos 34 veces más rápidos.

¡¡¡Pero incluso 34 veces más rápido es mucho !!!

En resumen, Usar DateTime.UtcNowes mucho más rápido queDateTime.Now

La única forma que encontré para mejorar la clase sugerida es usar código en línea: DateTime.UtcNow + LocalUtcOffset en lugar de llamar al método de la clase

Por cierto, intentar forzar al compilador a compilar en línea mediante el uso [MethodImpl(MethodImplOptions.AggressiveInlining)] no pareció acelerar las cosas.

Jonathan Weinreb avatar Oct 16 '2016 19:10 Jonathan Weinreb

Para responder en orden inverso:

2) No puedo pensar en una manera más rápida.

1) Valdría la pena comprobar si hay alguna mejora en el marco de trabajo como la que acaban de anunciar para System.IO.

Es difícil estar seguro de la seguridad, pero es algo que pide a gritos muchas pruebas unitarias. Me viene a la mente el horario de verano. El System One obviamente está muy curtido en batalla, mientras que el tuyo no.

 avatar Oct 13 '2009 17:10