Hub documentation
Deduplicação
Deduplicação
Repositórios habilitados para Xet utilizam divisão definida por conteúdo (CDC) para deduplicar no nível de bytes (~64KB de dados, também referidos como “chunk”). Cada chunk é identificado por um hash rolante que determina as fronteiras dos chunks com base no conteúdo real do arquivo, tornando-o resiliente a inserções ou exclusões em qualquer parte do arquivo. Quando um arquivo é enviado para um repositório baseado em Xet usando um cliente compatível com Xet, seu conteúdo é dividido nesses chunks de tamanho variável. Somente os novos chunks que ainda não estão presentes no armazenamento do Xet são mantidos após a divisão; todo o resto é descartado.
A deduplicação em nível de chunk também é o que torna cópias no lado do servidor instantâneas:
hf buckets cpentre repositórios e buckets migra apenas hashes de conteúdo, sem reenvio de dados. Veja Copiando arquivos entre repositórios e buckets.
Como o Content-Defined Chunking Funciona
Para entender o chunking definido por conteúdo, imagine um arquivo como uma longa passagem de texto. O sistema varre os dados usando um hash rolante — uma pequena função matemática que desliza sobre os bytes. Sempre que o hash atinge um padrão especial, um limite de chunk é colocado naquela posição. Como os limites são determinados pelo próprio conteúdo (e não por posições fixas), regiões idênticas de dados sempre produzem os mesmos chunks, mesmo que o conteúdo ao redor mude.
Por que não usar blocos de tamanho fixo?
Considere o que acontece quando você insere uma pequena quantidade de dados no meio de um arquivo. Com a divisão em blocos de tamanho fixo, todos os limites de bloco após a inserção são deslocados, invalidando todos os blocos subsequentes — mesmo que a maior parte dos dados permaneça inalterada:
Original file, fixed 6-byte chunks:
|The qu|ick br|own fo|x jump|s over| the l|azy do|g |
chunk1 chunk2 chunk3 chunk4 chunk5 chunk6 chunk7 chunk8
Insert "very " before "lazy":
|The qu|ick br|own fo|x jump|s over| the v|ery la|zy dog|
chunk1 chunk2 chunk3 chunk4 chunk5 chunk6 chunk7 chunk8
~~~~~~ ~~~~~~ ~~~~~~
3 chunks changed!Embora apenas 5 bytes tenham sido inseridos, 3 dos 8 blocos foram alterados porque todos os limites após a edição se deslocaram em 5 posições. Em arquivos reais com tamanho de bloco de 64KB, uma pequena edição pode invalidar centenas de megabytes de blocos.
O Chunking Definido por Conteúdo Mantém as Fronteiras Estáveis
Com o CDC, as fronteiras são definidas onde o conteúdo corresponde a um padrão — e não em intervalos fixos. Isso significa que uma inserção afeta apenas o bloco onde a edição ocorre. Os blocos antes e depois permanecem idênticos:
Original file, content-defined chunks (boundaries marked by "|"):
|The quick |brown fox |jumps over |the lazy dog|
chunk 1 chunk 2 chunk 3 chunk 4
Insert "very " before "lazy":
|The quick |brown fox |jumps over |the very lazy dog|
chunk 1 chunk 2 chunk 3 chunk 4'
(same) (same) (same) (changed)Apenas 1 dos 4 blocos foi alterado — aquele que contém a edição. Os outros três são idênticos byte a byte e são deduplicados. É por isso que o CDC é tão eficaz para dados versionados: ao atualizar um checkpoint de modelo ou adicionar linhas a um conjunto de dados, apenas as porções modificadas precisam ser enviadas e armazenadas.
De Chunks para Armazenamento
O pipeline completo de deduplicação funciona da seguinte forma:
Quando um arquivo é dividido em blocos, o hash de cada bloco é verificado em relação ao que já está armazenado. Isso ocorre em vários níveis: primeiro, em relação aos blocos já vistos na sessão de upload atual; em seguida, em relação a um cache local de metadados de uploads anteriores; e, por fim, um subconjunto de blocos é verificado em relação a todo o armazenamento do Xet por meio de uma consulta global de deduplicação. Blocos duplicados são ignorados por completo. Os blocos novos são agrupados em blocos de 64 MB e enviados. Cada bloco é armazenado uma única vez em um armazenamento endereçado por conteúdo (CAS), indexado pelo seu hash.
Economia de Armazenamento na Prática
A recomendação atual do Hub é limitar os arquivos a 200 GB. Com um tamanho de bloco de 64KB, um arquivo de 20GB possui 312.500 blocos, muitos dos quais permanecem inalterados de uma versão para outra. O Git LFS foi projetado para perceber apenas que um arquivo foi alterado e armazenar a totalidade daquela revisão. Ao deduplicar no nível dos blocos, o backend Xet permite armazenar apenas o conteúdo modificado em um arquivo (que pode ser de apenas alguns KB ou MB) e deduplica com segurança blocos compartilhados entre repositórios. Para os grandes arquivos binários encontrados em repositórios de Model e Dataset, isso proporciona melhorias significativas nos tempos de transferência de arquivos.
Para mais detalhes, consulte os posts de blog De Arquivos para Chunks e De Chunks para Blocks, ou o paper Git is for Data de Low et al. que serviu como ponto de partida para o XetHub antes de ser adquirido pela Hugging Face.
Update on GitHub