¿Por qué el JavaScript minificado u ofuscado se comporta peor que el código sin comprimir?
performance obfuscation (3)
Me encontré con este informe de rendimiento de código JavaScript comprimido utilizando varios minificadores y ofuscadores. Lo que sorprende es que, aparte del modo avanzado de cierre, en la mayoría de los casos, todos los demás códigos de salida de minificadores tienen un rendimiento peor que el código sin comprimir. ¿Cómo explicamos eso?
Desplácese hasta el final de la página para ver el informe. Aquí hay capturas de pantalla:
Leyenda:
- Azul - Compresor YUI
- Rojo - Cierre (modo avanzado)
- Naranja - Cierre (modo básico)
- Verde - JS Min
- Púrpura - JS Packer
- Azul claro - UglifyJS
- Rosa - Código sin comprimir
Parece que puede haber confundido inadvertidamente minificación con ofuscación.
Para entender las dos tecnologías, las explicaré por separado.
La minificación es un proceso en el que el tamaño de un archivo de origen se reduce y se convierte en un formato destinado a una legibilidad de la máquina más eficiente. Esto se hace (a) eliminando comentarios y espacios en blanco innecesarios, y posiblemente (b) reemplazando nombres de variables con nombres de variables simples e incrementales que a menudo comienzan con un carácter. El código resultante sigue funcionando igual que el código original, pero es teóricamente más rápido para que el navegador lo analice y compile.
La ofuscación es una técnica en la que el código se modifica para que ya no sea reconocible como el código fuente original y, a menudo, se usa para desalentar la ingeniería inversa del código propietario. Algunos de los cambios pueden tener una sobrecarga, por ejemplo, el código se puede cifrar y luego descifrar de nuevo en el tiempo de ejecución. Dicho esto, es típico que un ofuscador de código también termine el trabajo al minimizar la salida.
Sin embargo, se podría considerar que la minificación es una forma burda de ofuscación, pero generalmente tales procesos se llevan a cabo más con propósitos de rendimiento y / o ancho de banda.
Primero, permítame jugar al defensor del diablo: el código no "ejecuta" nada en realidad (nada serio, quiero decir, excepto JS Packer). Es esencialmente una definición de funciones, objetos y propiedades.
JS Packer no produce código JavaScript, sino texto comprimido que se debe desempaquetar en tiempo de ejecución. Por eso es mucho más lento. El cierre de Google mediante optimización avanzada reemplaza los identificadores siempre que sea posible. Así que ya tiene que haber una ventaja de rendimiento al analizar el script.
Dicho esto, es posible sacrificar el rendimiento por el tamaño del código. Un ejemplo es reemplazar true
y false
con !0
y !1
. Sin embargo, depende del motor de JavaScript. Podría ser optimizado por el motor antes de la primera llamada, después de él, después de algunas llamadas, nunca ... quién sabe;)
Nuevos hallazgos
Mientras tanto, hice algunos perfiles y me di cuenta de que olvidé una cosa: la recolección de basura. La influencia puede ser suficiente para explicar algunas de las diferencias entre los scripts y los navegadores (¡diferentes motores!).
Combine eso con el hecho de que el código no hace mucho y usted tiene algo. En una prueba tuve un tiempo de CPU para la recolección de basura de aproximadamente el 3% para los no comprimidos y el 9% (!) Para JSMin. Lo que significa resultados completamente diferentes para código casi igual.
Hallazgos aún más nuevos
Cuando ejecutas JSMin primero es más rápido que sin comprimir. Intenté esto varias veces y siempre obtuve el mismo resultado. Esto confirma los hallazgos anteriores. Estoy bastante confiado ahora, que encontramos la solución.
Sí, la ofuscación puede causar algunos problemas de rendimiento, pero no es cierto que el código minificado se comporte peor que uno sin comprimir. De hecho, el código minimizado funciona mejor que uno no comprimido. Esto se debe a que el código minifiado tiene un nombre de función / variable mucho más corto, lo que hace que la llamada de referencia al espacio de memoria asignado sea mucho más fácil.