¿Por qué las compilaciones incrementales en "make" no usan algoritmos hash?

10

Soy un principiante makey me pregunto cuándo usarlo make clean.

Un colega me dijo que las compilaciones incrementales makese basan en las marcas de tiempo de los archivos. Por lo tanto, si revisa una versión anterior de un archivo en su VCS, tendrá una marca de tiempo "antigua" y se marcará como "no es necesario volver a compilar este archivo". Entonces, ese archivo no se incluiría en la próxima compilación.
Según ese mismo colega, sería una razón para usar make clean.

De todos modos, recibí la respuesta a la pregunta "cuándo usar make clean" de otras preguntas de StackExchange, pero mi otra pregunta es:

¿Por qué las compilaciones incrementales que se makebasan en marcas de tiempo de archivos y no en SHA-1 por ejemplo? Git, por ejemplo, muestra que podemos determinar con éxito si un archivo se modificó utilizando el SHA-1.
¿Es por problemas de velocidad?

Filaton
fuente
55
makefue creado en los años 70. SHA-1 fue creado en los años 90. Git fue creado en los años 00. Lo último que desea es que algunas compilaciones oscuras que estuvieron funcionando durante 30 años fallaran repentinamente porque alguien decidió modernizarse con un sistema probado.
Ordous
1
Hashing los archivos todo el tiempo es lento. Creo que git también usa metadatos del sistema de archivos para optimizar sus comprobaciones de archivos modificados.
CodesInChaos
44
La solución original basada en fechas de archivo es muy simple, no necesita ningún archivo adicional para almacenar los códigos hash, y funcionó notablemente bien durante varias décadas. ¿Por qué alguien debería reemplazar una solución que funciona bien por una más complicada? Además, la mayoría de los sistemas AFCS VCS asignan a los archivos desprotegidos la "fecha de salida", por lo que los archivos modificados provocarán una recompilación correcta sin "limpiar".
Doc Brown
@Ordous: Divertido, pero ¿es relevante aquí? El software no se oxida; se rinde porque alguien cambió algo en el entorno circundante. A menos que no lo hicieran, en cuyo caso aún debería funcionar.
Robert Harvey
1
@RobertHarvey ¡Por supuesto que sí! Claro, si no actualiza su makesoftware, entonces su software no se romperá, sin embargo, makehace un esfuerzo por tener compatibilidad con versiones anteriores. Cambiar el comportamiento central sin una buena razón es más o menos lo contrario de eso. Y las fechas muestran por qué no se hizo originalmente para usar SHA-1, o por qué no fue fácil adaptarlo cuando estuvo disponible ( makeya tenía décadas de antigüedad).
Ordous

Respuestas:

7

Un problema obvio (y posiblemente superficial) sería que el sistema de compilación tendría que mantener un registro de los hash de los archivos que se utilizaron para la última compilación. Si bien este problema ciertamente podría resolverse, requeriría almacenamiento lateral cuando la información de marca de tiempo ya está presente en el sistema de archivos.

Sin embargo, más en serio, el hash no transmitiría la misma semántica. Si sabe que el archivo T se creó a partir de la dependencia D con el hash H 1 y luego descubre que D ahora se convierte en hash a H 2 , ¿debería reconstruir T ? Probablemente sí, pero también podría ser que H 2 en realidad se refiera a una versión anterior del archivo. Las marcas de tiempo definen un orden, mientras que los hash solo son comparables para la igualdad.

Una característica que admite las marcas de tiempo es que simplemente puede actualizar la marca de tiempo (por ejemplo, utilizando la utilidad de línea de comandos POSIX touch) para engañar makey pensar que una dependencia ha cambiado o, lo que es más interesante, que un objetivo es más reciente de lo que realmente es. Si bien jugar con esto es una gran oportunidad para dispararte en el pie, es útil de vez en cuando. En un sistema basado en hash, necesitaría soporte del propio sistema de compilación para actualizar su base de datos interna de hashes utilizados para la última compilación sin realmente construir nada.

Si bien ciertamente se podría argumentar el uso de hashes sobre marcas de tiempo, mi punto es que no son una mejor solución para lograr el mismo objetivo, sino una solución diferente para lograr un objetivo diferente. Cuál de estos objetivos es más deseable podría estar abierto a debate.

5gon12eder
fuente
1
Si bien la semántica difiere entre los hashes y las marcas de tiempo, normalmente es irrelevante en este caso, ya que lo más probable es que desee una compilación basada en los archivos actuales, sin importar su edad.
axl
La mayor parte de lo que dices es correcto. Sin embargo, un sistema de compilación bien implementado que utiliza hashes como Google Blaze / Bazel (la versión interna de Blaze, la de código abierto es Bazel) supera a un sistema con marca de tiempo como Make. Dicho esto, debe hacer un gran esfuerzo en las compilaciones repetibles para que siempre sea seguro usar artefactos de compilación antiguos en lugar de reconstruir.
btilly
El mapeo aquí no es muchos a uno, es uno a uno. Si Dahora tiene problemas H2, y no tiene una salida T2construida D@H2, debe producirla y almacenarla. A partir de entonces, independientemente del orden de Dcambio entre los estados H1y H2, podrá utilizar la salida en caché.
Asad Saeeduddin
1

Hashing un proyecto completo es muy lento. Tienes que leer cada byte de cada archivo. Git no hace hash en cada archivo cada vez que ejecutas uno de los git statusdos. Tampoco los pagos de VCS normalmente establecen el tiempo de modificación de un archivo al tiempo original creado. Una restauración de respaldo lo haría, si tiene cuidado de hacerlo. Toda la razón por la que los sistemas de archivos tienen marcas de tiempo es para casos de uso como estos.

Un desarrollador generalmente se ejecuta make cleancuando una dependencia no directamente rastreada por los cambios de Makefile. Irónicamente, esto generalmente incluye el Makefile mismo. Por lo general, también incluye versiones del compilador. Dependiendo de qué tan bien esté escrito su Makefile, podría incluir versiones de bibliotecas externas.

Este es el tipo de cosas que tienden a actualizarse cuando se realiza una actualización de control de versiones, por lo que la mayoría de los desarrolladores solo tienen la costumbre de ejecutar una make cleanal mismo tiempo, para que sepa que está comenzando desde cero. Puede escapar sin hacerlo muchas veces, pero es realmente difícil predecir los momentos en que no puede hacerlo.

Karl Bielefeldt
fuente
Puede usar sistemas de archivos como ZFS, donde el costo del hash se amortiza a lo largo del tiempo cuando se modifican los archivos, en lugar de pagarse de una vez cuando construye.
Asad Saeeduddin
1

Algunos puntos sobre hashes vs marcas de tiempo en sistemas de compilación:

  1. Cuando desprotege un archivo, la marca de tiempo debe actualizarse a la hora actual, lo que desencadena una reconstrucción. Lo que su colega describe no suele ser un modo de falla de los sistemas de marca de tiempo.
  2. Las marcas de tiempo son marginalmente más rápidas que los hashes. Un sistema de marca de tiempo solo tiene que verificar la marca de tiempo, mientras que un sistema hash debe verificar la marca de tiempo y luego potencialmente el hash.
  3. Make está diseñado para ser ligero y autónomo. Para superar (2), los sistemas basados ​​en hashe generalmente ejecutarán un proceso en segundo plano para verificar hashes (por ejemplo, Watchman de Facebook ). Esto es contrario a los objetivos de diseño (e historia) de Make.
  4. Los hashes evitan reconstrucciones innecesarias cuando una marca de tiempo ha cambiado pero no el contenido. A menudo, esto compensa el costo de calcular el hash.
  5. Los hashes permiten que los cachés de artefactos se compartan entre proyectos y en una red. Nuevamente, esto más que compensa el costo de calcular hashes.
  6. Los sistemas de compilación modernos basados ​​en hash incluyen Bazel (Google) y Buck (Facebook).
  7. La mayoría de los desarrolladores deberían considerar el uso de un sistema basado en hash, ya que no tienen los mismos requisitos que aquellos bajo los cuales se diseñó Make.
sdgfsdh
fuente