Ya sea rápido o mal

imagen


En 2018, practiqué Advent of Code (puedes ver las transmisiones de mis soluciones aquí ). Todos los días de diciembre, publican un pequeño problema y tienes que escribir un programa que lo resuelva. Por lo general, toma desde un par de minutos hasta un par de horas y es bastante divertido, te recomiendo que lo pruebes. Cuando se completa una tarea, siempre está disponible, no solo en diciembre.



Me di cuenta de que hay dos tipos de soluciones: las que pueden calcular la respuesta en un par de milisegundos y las que llevan la respuesta durante varios años. Si obtiene la segunda opción, está haciendo algo mal. No tiene sentido esperar, aunque, técnicamente, eso también podría ser correcto.



Otra observación interesante es que no importa qué hardware uses para iniciar. Si la solución es rápida, será rápida tanto en la computadora portátil como en la estación de trabajo con bombeo. Por supuesto, podría ser dos o tres veces más lento, pero la diferencia estará entre 10ms y 30ms. Obtendrá su respuesta de todos modos, por lo que realmente no importa.



Por otro lado, si la solución es lenta, puede usar cualquier potencia de procesamiento y aún así no será suficiente. Esto podría reducir el tiempo de ejecución de tres años (en una computadora portátil) a un año (en la computadora más poderosa que puedo construir). ¿Cual es la diferencia? De todos modos, es demasiado largo.



Ahora pasemos al software. Es fácil decir que las soluciones de Advent Of Code son incorrectas cuando son lentas, ya que sabemos que debe existir una solución rápida. Con problemas reales, nadie lo garantiza.



Excepto en algunos casos.



De hecho, muy a menudo.



De hecho, diría que casi siempre.



Veamos. Tengo una biblioteca llamada Datascript . Es una estructura / base de datos persistente y da la casualidad de que está implementada para dos plataformas: JS y JVM. Además, en realidad está escrito en Clojure y ambas plataformas utilizan la mayor parte de su código base. Esto significa que sabemos que ambas versiones siempre hacen lo mismo. Hay una pequeña capa que cubre detalles específicos de la plataforma, como los tipos de datos y la biblioteca estándar, pero el resto es genérico. No es que una versión sea la original y la otra sea un puerto ineficiente. Ambos juegan el mismo juego.



Podrías estar pensando que si se comportan igual, su desempeño debería ser el mismo, ¿verdad? Sería lógico pensar que sí.



Echemos un vistazo al tiempo real que lleva compilar el código base y ejecutar el conjunto completo de pruebas de integración. Estamos hablando de una base de código que tiene poco más de 9000 LOC, de los cuales 4000 son pruebas:



Clojure 1.10 en JVM:



  • Tiempo de arranque REPL: 1,5 segundos
  • Tiempo de compilación: 6,5 segundos
  • Tiempo de pruebas: 0,45 seg.


ClojureScript 1.10.439 con compilación avanzada:



  • Tiempo de compilación: 78 segundos
  • Tiempo de pruebas: 1 seg.


ClojureScript 1.10.439 sin compilación de cierre de Google:



  • Tiempo de compilación: 24 segundos
  • Tiempo de pruebas: 1,3 seg.


Entonces, ¿qué nos dicen estos números? Básicamente, puede tomar ~ 8 segundos, 24 segundos o 78 segundos para procesar el mismo código. La decisión es tuya. Además, al ejecutar el mismo programa, puede obtener el resultado en medio segundo, un segundo o casi un segundo y medio.



Pero espera, Tonsky, ¡no se pueden comparar! ¡Éstas son dos grandes diferencias! ¡Están diseñados para hacer cosas completamente diferentes! ¡Uno de ellos funciona en un navegador! "



Por supuesto, puede obtener resultados. Permítanme recordarles que estamos compilando el mismo código, construido para hacer lo mismo, usando los mismos algoritmos y ejecutándonos en el mismo hardware. El resultado final es el mismo en ambos casos: obtiene una respuesta a su consulta en el registro de datos en poco tiempo o durante mucho tiempo. O te pasas la mitad del día esperando el compilador o lo pasas jugando al REPL, construyendo algo.



¿Qué han estado haciendo los compiladores de ClojureScript / Google Closure durante tanto tiempo? Están perdiendo el tiempo, eso es. Por supuesto, nadie tiene la culpa, pero al final toda la decisión es simplemente incorrecta. Podemos hacer lo mismo mucho más rápido, tenemos pruebas, tenemos los medios para hacerlo, pero da la casualidad de que no es así. Pero podríamos. Si quieres. Esta enorme sobrecarga que paga, la paga en vano. No obtiene nada de JS más que duplicar el tiempo de ejecución y los tiempos de construcción astronómicos.



Lo mismo es cierto para todos los lenguajes con tiempos de construcción terriblemente largos. No es que no pudieran ser más rápidos. Simplemente eligen no hacerlo. ¿Un programa C ++ o Rust tarda demasiado en compilarse? Bueno, OCaml probablemente podría compilar un programa equivalente en menos de un segundo. Y seguirá siendo rápido a nivel de coche.



“¡Guau, guau, más despacio! ¡Esto es aún más injusto! Ahora no son solo dos grandes diferencias, ahora es como cepillos de dientes y naves espaciales. Ignoras por completo lo que ofrece cada idioma. Hay una razón por la que pasan tanto tiempo compilando, ¿sabes? "



Sé. Pero aún así, creo que puedes compararlos. Después de todo, todos son lenguajes de uso general y, al final, lo que importa es si tiene un programa funcional a mano y puede proporcionar una respuesta en un plazo razonable. No importa cómo llegó el desarrollador. Puedes calmarte pensando que lo es, pero a nadie le importa.



Imagínese: un avión vuela desde Moscú a Novosibirsk, el corazón de Siberia, que recorre 2.800 kilómetros en 4 horas. También hay un tren que recorre la misma distancia en tres días. No hay ducha en el tren, mala comida, camas en las que no se puede dormir. Y un avión es un cómodo avión moderno. ¿Cuál escogerías? El mismo precio. La única diferencia es su comodidad y su tiempo.



imagen



Si tomamos esto como una metáfora del desarrollo de software, se sorprenderá de que los programadores tomen el tren con alegría. Incluso argumentan hasta el punto de la ronquera que hay razones irrefutables para elegir un tren. No, no les importa si el compilador se toma el tiempo para "trabajar". Sin embargo, existen formas más rápidas de llegar al mismo destino. Es fácil confundirse al discutir sobre detalles, pero recuerde: todos terminamos en el mismo lugar , sin importar el idioma que hablemos.



Navegadores? La misma historia. HTML es una forma bastante ineficaz de colocar píxeles en la pantalla. Una computadora que podría mostrar millones de polígonos en un marco puede tener dificultades para cargar una página web. Al igual que con las soluciones de Advent of Code, esto no depende de la potencia de su computadora. E incluso el código web altamente optimizado basado en Canvas y WebAssembly ( Figma ) mantiene a los fanáticos de mi Macbook girando en completo silencio cuando lanzo mi propio Sketch.



imagen



- * palmaditas en la portada * Esta PC es capaz de ejecutar Crysis 3 en 4K a 144 fps.

- ¿Pero puede ejecutar Atom?




Simplemente hay límites a lo lejos que puede llegar esta decisión equivocada. Los editores de texto en Electron no pueden cambiar el tamaño de la ventana en tiempo real y combarse en marcos cuando simplemente mueve el cursor. La holgura en el iMac Pro será tan lenta e intensiva en memoria como en una Macbook de 12 pulgadas.



La decisión completa, la "pila web", es generalmente incorrecta . Se podría hacer lo mismo de manera más rápida y eficiente: hay mucho potencial desperdiciado. Es hora de admitirlo y empezar de nuevo. Hay editores de texto rápidos y programas de comunicación que están fácilmente disponibles incluso para los netbooks más débiles.



Puedo seguir y seguir. Tenga en cuenta esto: piense en lo que obtiene de él. ¿Son comparables el problema y los recursos gastados en él? Es fácil encontrar excusas de por qué las cosas son como son. Probablemente todos sean válidos, pero son excusas. Sabemos que los programas más rápidos son posibles y eso hace que todo lo demás simplemente salga mal.



All Articles