Comparativo de desempeño para formato de fechas

Comparto esto para los que tengan la misma duda que yo tenía: Saber si es más rápido usar   o un   para formatear una fecha.

Es claro que   puede ser más simple de codificar, sobre todo en ambientes concurrentes, ya que SimpleDateFormat no es thread-safe y por tanto hay que usarlo solamente de manera local o bien envolverlo en un  .

Pero pues hice un programa muy simple en Groovy para comparar el performance de ambos:

 

Después de ejecutar esto varias veces, el resultado es bastante consistente: El primer ciclo de formatear la fecha 10mil veces tarda ~40ms mientras que el siguiente ciclo con String.format tarda ~120ms. Es decir,   tarda el triple de lo que tarda  .

Incluso si cambiamos el formato por uno más estándar, digamos yyyy-MM-dd, que para String.format es simplemente %tF, los tiempos son ~10ms con SimpleDateFormat contra ~40ms con String.format.

Con DecimalFormat ocurre algo similar: para formatear un BigDecimal con DecimalFormat a dos decimales, tarda ~100ms y con String.format (usando simplemente %.2f) tarda ~350ms.

Tanto para fechas como para números, cada alternativa tiene sus ventajas; SimpleDateFormat evidentemente es bastante más rápido, pero String.format es más fácil de usar, sobre todo si se usan los formatos estándar com tF y tT. Por otra parte, DecimalFormat es bastante completo para formateo de números con separadores de miles, símbolos de moneda, etc, pero no se puede definir una longitud fija mientras que son String.format sí (por ejemplo %9.2f que rellena con espacios a la izquierda para que quede a 9 posiciones en total).

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de greeneyed

La explicación de por qué uno

La explicación de por qué uno tiene más rendimiento que otro parece bastante claro, teniendo en cuenta que el análisis del formato a utilizar se hace 1 sola vez en el caso de SimpleDateFormat y se hace cada vez en el caso de String.format. El caso sería poder crear un "formater" usando el formato de String.format, y utilizarlo como SimpleDateFormat dentro del bucle, pero el API no da esa opción, que yo sepa.

Así que como bien dices, ahora mismo es una cuestión de rendimiento vs flexibilidad.

Imagen de ezamudio

lo curioso

Lo curioso es el caso de formatos como   que ya son por decirlo de alguna forma "prefabricados", y por tanto esperaría que fuera igual o más rápido con  , ya que es equivalente a usar   pero aún así es más rápido el SimpleDateFormat.

Imagen de greeneyed

Bueno, la cuestión es que

Bueno, la cuestión es que cuando creas el SimpleDateFormat, la cadena que define el formato se parsea, se interpreta, se buscan errores etc. UNA VEZ. Luego al ejecutar el format simplemente se extraen los datos requeridos y se "pinta".

En cambio al llamar a String.format, CADA VEZ has de parsear la cadena que define el formato, y luego ejecutar el format.

Yo diría que esa es la diferencia. Si creas un SimpleDateFormat en cada iteración del bucle, el trabajo realizado en ambas soluciones sería más parecido, aunque en ese caso seguramente SimpleDateFormat sea más lento.