Por que construções incrementais no "make" não usam algoritmos de hash?

10

Eu sou iniciante makee estou pensando em quando usar make clean.

Um colega me disse que as compilações incrementais makesão baseadas nos registros de data e hora dos arquivos. Portanto, se você fizer o check-out de uma versão antiga de um arquivo no seu VCS, ele terá um carimbo de data / hora "antigo" e será marcado como "não há necessidade de recompilar esse arquivo". Em seguida, esse arquivo não seria incluído na próxima compilação.
Segundo o mesmo colega, seria uma razão para usar make clean.

De qualquer forma, obtive a resposta para a pergunta "quando usar make clean" de outras perguntas do StackExchange, mas minha outra pergunta é:

Por que construções incrementais usando makecontam com registros de data e hora de arquivos e não no SHA-1, por exemplo? O Git, por exemplo, mostra que podemos determinar com êxito se um arquivo foi modificado usando o SHA-1.
É por problemas de velocidade?

filaton
fonte
5
makefoi criado nos anos 70. O SHA-1 foi criado nos anos 90. O Git foi criado nos anos 00. A última coisa que você deseja é que algumas construções obscuras que estavam trabalhando há 30 anos falhem repentinamente porque alguém decidiu se modernizar com um sistema testado e comprovado.
Ordous
1
Hashing dos arquivos o tempo todo é lento. Eu acho que o git também usa metadados do sistema de arquivos para otimizar suas verificações de arquivos alterados.
CodesInChaos
4
A solução original com base nas datas dos arquivos é muito simples, não precisa de nenhum arquivo adicional para armazenar os códigos de hash e funcionou notavelmente bem ao longo de várias décadas. Por que alguém deve substituir uma solução que funcione bem por outra mais complicada? Além disso, a maioria dos sistemas VCS da AFAIK atribui aos arquivos retirados a "data de saída", portanto, os arquivos alterados causarão corretamente uma recompilação sem "limpar".
Doc Brown
@ Ordous: Divertido, mas é relevante aqui? O software não enferruja; isso acontece porque alguém mudou algo no ambiente ao redor. A menos que não, nesse caso, ainda deve funcionar.
Robert Harvey
1
@RobertHarvey Claro que é! Claro, se você não atualizar o makeseu software, ele não quebrará, no entanto, makefaz um esforço para ter compatibilidade com versões anteriores em novas versões. Mudar o comportamento do núcleo sem uma boa razão é praticamente o oposto disso. E as datas mostram por que não foi originalmente feito para usar o SHA-1 ou por que não foi fácil adaptá-lo quando ficou disponível ( makejá tinha décadas antes).
Ordous

Respostas:

7

Um problema óbvio (e sem dúvida superficial) seria que o sistema de compilação teria que manter um registro dos hashes dos arquivos que foram usados ​​para a última compilação. Embora esse problema possa certamente ser resolvido, seria necessário armazenamento lateral quando as informações de registro de data e hora já estivessem presentes no sistema de arquivos.

Mais seriamente, porém, o hash não transmitiria a mesma semântica. Se você sabe que arquivo T foi construído a partir de dependência D com hash de H 1 e, em seguida, descobrir que D agora hashes de H 2 , você deve re-build T ? Provavelmente sim, mas também pode ser que o H 2 realmente se refira a uma versão mais antiga do arquivo. Os carimbos de hora definem uma ordem, enquanto os hashes são comparáveis ​​apenas para igualdade.

Um recurso que os carimbos de data / hora suportam é que você pode simplesmente atualizar o carimbo de data / hora (por exemplo, usando o utilitário de linha de comando POSIX touch) para tentar makepensar que uma dependência mudou ou - mais interessante - um destino é mais recente do que realmente é. Embora brincar com isso seja uma ótima oportunidade de se acertar no pé, é útil de vez em quando. Em um sistema baseado em hash, você precisaria de suporte do próprio sistema de compilação para atualizar seu banco de dados interno de hashes usados ​​para a última compilação sem criar nada.

Embora possa certamente ser argumentado o uso de hashes ao longo do tempo, meu argumento é que eles não são uma solução melhor para atingir o mesmo objetivo, mas uma solução diferente para atingir um objetivo diferente. Qual desses objetivos é mais desejável pode estar aberto ao debate.

5gon12eder
fonte
1
Embora a semântica seja diferente entre hashes e carimbos de hora, é normalmente irrelevante nesse caso, pois você provavelmente deseja uma compilação com base nos arquivos atuais, independentemente da idade.
axl
A maior parte do que você diz está correta. No entanto, um sistema de compilação bem implementado que usa hashes como o Google blaze / bazel (a versão interna do blaze, a de código aberto é o bazel) supera as calças de um sistema com timestamp como o Make. Dito isso, é necessário muito esforço em construções repetíveis, para que seja sempre seguro usar artefatos de construção antigos em vez de reconstruir.
btilly 25/05
O mapeamento aqui não é muitos para um, é um para um. Se Dagora for hash H2, e você não tiver uma saída T2criada D@H2, precisará produzi-la e armazená-la. Posteriormente, independentemente de qual ordem Dalterna entre os estados H1e H2, você poderá usar a saída em cache.
Asad Saeeduddin
1

Hashing de um projeto inteiro é muito lento. Você precisa ler todos os bytes de cada arquivo. O Git não mistura todos os arquivos sempre que você executa um git status. Os check-outs VCS também não definem normalmente a hora de modificação de um arquivo para a hora original de criação. Uma restauração de backup seria, se você tomar o cuidado de fazê-lo. Todo o motivo pelo qual os sistemas de arquivos têm registros de data e hora é para casos de uso como estes.

Um desenvolvedor normalmente é executado make cleanquando uma dependência não diretamente rastreada pelo Makefile é alterada. Ironicamente, isso geralmente inclui o próprio Makefile. Geralmente também inclui versões do compilador. Dependendo da qualidade do seu Makefile, ele pode incluir versões de bibliotecas externas.

Esses são os tipos de coisas que tendem a ser atualizadas quando você faz uma atualização de controle de versão; portanto, a maioria dos desenvolvedores adquire o hábito de executá- make cleanlos ao mesmo tempo, para que saiba que está começando de uma forma limpa. Você pode fugir sem fazer isso o tempo todo, mas é realmente difícil prever os horários que você não pode.

Karl Bielefeldt
fonte
Você pode usar sistemas de arquivos como o ZFS, onde o custo do hash é amortizado ao longo do tempo em que os arquivos estão sendo modificados, em vez de ser pago de uma só vez ao criar.
Asad Saeeduddin
1

Alguns pontos sobre hashes versus timestamps em sistemas de compilação:

  1. Quando você faz o check-out de um arquivo, o registro de data e hora deve ser atualizado para o horário atual, o que aciona uma reconstrução. O que seu colega descreve não é geralmente um modo de falha dos sistemas de registro de data e hora.
  2. Os carimbos de hora são marginalmente mais rápidos que os hashes. Um sistema de registro de data e hora precisa apenas verificar o registro de data e hora, enquanto um sistema de hash deve verificar o registro de data e hora e, potencialmente, o hash.
  3. O Make foi projetado para ser leve e independente. Para superar (2), os sistemas baseados em hashe geralmente executam um processo em segundo plano para verificar hashes (por exemplo, o Watchman do Facebook ). Isso é contrário aos objetivos de design (e histórico) do Make.
  4. Hashes evitam reconstruções desnecessárias quando um carimbo de data e hora é alterado, mas não o conteúdo. Muitas vezes, isso compensa o custo da computação do hash.
  5. Hashes permitem que caches de artefato sejam compartilhados entre projetos e em uma rede. Novamente, isso mais do que compensa o custo dos hashes de computação.
  6. Os modernos sistemas de compilação baseados em hash incluem Bazel (Google) e Buck (Facebook).
  7. A maioria dos desenvolvedores deve considerar o uso de um sistema baseado em hash, pois eles não têm os mesmos requisitos daqueles sob os quais o Make foi projetado.
sdgfsdh
fonte