Почему папка Git .git / objects / подразделяется на многие папки с префиксами SHA?

21

Git внутренне хранит объекты (Blobs, деревья) в .git/objects/папке. На каждый объект может ссылаться хеш SHA1, который вычисляется из содержимого объекта.

Тем не менее, объекты не хранятся внутри .git/objects/папки напрямую. Вместо этого каждый объект хранится в папке, которая начинается с префикса его хэша SHA1. Таким образом, объект с хешем b7e23ec29af22b0b4e41da31e868d57226121c84будет храниться в.git/objects/b7/e23ec29af22b0b4e41da31e868d57226121c84

Почему Git так подразделяет хранилище своих объектов?

Ресурсы, которые я мог найти, такие как страница о внутренностях Git на git-scm, только лишь объясняли, как , а не почему .

Qqwy
источник

Ответы:

33

Можно поместить все файлы в один каталог, хотя иногда это может стать немного большим. Многие файловые системы имеют ограничение . Вы хотите поместить репозиторий git на диск в формате FAT32 на флешку? Вы можете хранить только 65 535 файлов в одном каталоге. Это означает, что необходимо подразделить структуру каталогов так, чтобы заполнение одного каталога было менее вероятным.

Это может даже стать проблемой с другими файловыми системами и более крупными git-репозиториями. Относительно небольшой репозиторий Git, который я вывешивал (около 360 МБ), и он имеет 181 546 объектов для файлов размером 11 КБ. Потяните репозиторий Linux, и вы получите 4 374 054 объекта. Если бы вы поместили все это в один каталог, было бы невозможно проверить и вывести из строя (для некоторого значения «крах») файловую систему.

Так? Вы делите это на байт. Подобные подходы делаются с приложениями, такими как FireFox:

~/Li/Ca/Fi/Pr/7a/Cache $ ls
0/           4/           8/           C/           _CACHE_001_
1/           5/           9/           D/           _CACHE_002_
2/           6/           A/           E/           _CACHE_003_
3/           7/           B/           F/           _CACHE_MAP_

Помимо этого, это также касается вопроса производительности. Рассмотрим производительность NTFS с множеством длинных имен файлов :

Windows NT занимает много времени для выполнения операций с каталогами на дисках, отформатированных в файловой системе Windows NT (NTFS), которые содержат большое количество файлов с длинными именами файлов (имена, которые не соответствуют соглашению 8.3) в одном каталоге.

Когда NTFS перечисляет файлы в каталоге, она должна искать имена 8.3, связанные с длинными именами файлов. Поскольку каталог NTFS поддерживается в отсортированном состоянии, соответствующие длинные имена файлов и имена 8.3, как правило, не находятся рядом друг с другом в списке каталогов. Таким образом, NTFS использует линейный поиск в каталоге для каждого файла. В результате количество времени, необходимое для выполнения листинга каталога, увеличивается с квадратом количества файлов в каталоге. Для небольшого количества файлов (менее нескольких сотен) задержка незначительна. Но поскольку количество файлов в каталоге увеличивается до нескольких тысяч, время, необходимое для выполнения листинга, может увеличиться до минут, часов или даже дней. Проблема усугубляется, если длинные имена файлов очень похожи - отличаются только последними несколькими символами.

С файлами, названными в честь контрольных сумм SHA1, это может стать рецептом катастрофы и ужасной производительности.

Хотя приведенное выше взято из технической заметки Windows NT 3.5 (и NTFS 1.2 - обычно используемой с 1995 по начало 2000-х годов), это также можно увидеть в таких вещах, как EXT3, где реализации файловой системы представляют собой связанные списки, требующие поиска O (n) , И даже с этим изменением B-дерева:

Хотя алгоритм HTree значительно улучшил время поиска, он может привести к некоторым спадам производительности для рабочих нагрузок, использующих readdir () для выполнения некоторых операций со всеми файлами в большом каталоге.
...
Одно из возможных решений для смягчения этой проблемы производительности, которое было предложено Дэниелом Филлипсом и Андреасом Дилгером, но еще не реализовано, заключается в том, что ядро ​​выбирает свободные иноды, номера инодов которых соответствуют свойству, которое группирует иноды по их хэшу имени файла. Дэниел и Андреас предлагают выделить инод из диапазона инодов на основе размера каталога, а затем выбрать свободный инод из этого диапазона на основе хэша имени файла. Теоретически это должно уменьшить количество изменений, возникающих при доступе к инодам, указанным в каталоге, в порядке чтения. Однако не ясно, что эта стратегия приведет к ускорению; фактически это может увеличить общее количество блоков inode, на которые, возможно, придется ссылаться, и, таким образом, ухудшить производительность рабочих нагрузок readdir () + stat (). Очевидно, что

Кстати, этот бит о том, как улучшить производительность, был с 2005 года, в том же году был выпущен git.

Как видно из Firefox и многих других приложений, которые имеют много файлов с хеш-кешированием, дизайн разбивает кэш по байтам. Он имеет незначительные затраты производительности, и при использовании кроссплатформенности с системами, которые могут быть немного устаревшими, вполне может быть разница между работающей программой или нет.

Сообщество
источник
1
Вы заметили, что статья о производительности NTFS, из которой вы цитируете, относится к NT 3.5, выпущенной в 1994 году, верно?
Авнер Шахар-Каштан
1
@ AvnerShahar-Каштан, да. Git был выпущен в 2005 году. Я знаю, что я использовал файловые системы на базе NTFS v1.2 в корпоративной среде в начале 2000-х годов (тем не менее, в технической компании). Несомненно, в то время существует определенное совпадение между требованиями git и файловыми системами в общедоступных системах.
Возможно, было бы более понятным, если бы вы заявили, что это может быть историческим артефактом состояния технологии, когда был представлен git, потому что в его нынешнем виде вопрос, заданный в 2015 году, цитирует двадцатилетнее техническое ограничение (отказавшись от ответа кажется сбивающим с толку.
Авнер Шахар-Каштан
Честно говоря, система git«pack» смягчает многие из этих проблем. Теоретически, gitможно использовать только один каталог и просто перепаковывать, когда количество файлов в этом каталоге превышает определенный (возможно, зависящий от FS) предел.
nneonneo
5
@ AvnerShahar-Kashtan Если вы прочитаете связанную статью SO, вы увидите, что работа с каталогами, содержащими большое количество файлов, проблематична в нескольких файловых системах и операционных системах, а не только в NT 3.5. Помимо ограничений на файлы, даже простое перечисление файлов может повлечь за собой большие накладные расходы.
8

Есть две причины, почему это желательно.

Каталоги не могут быть сколь угодно большими. Например, некоторые (достаточно современные!) Файловые системы ограничены 32000 записей в одном каталоге. Количество коммитов в ядре Linux находится в таком порядке. Подразделение коммитов их первыми двумя шестнадцатеричными цифрами ограничивает размер верхнего уровня до 256 записей. Подкаталоги будут намного меньше для типичных репозиториев git.

Каталоги сканируются линейно. В некоторых файловых системах (например, семейство Ext *) каталог представляет собой связанный список или таблицу записей. Чтобы найти файл, весь список сканируется, пока не будет найдено подходящее имя файла. Понятно, что это нежелательно для производительности. Многие современные файловые системы дополнительно используют хеш-таблицы или B-деревья для быстрого поиска, но не у всех они могут быть. Хранение каждого каталога маленьким означает быстрое время доступа.

Амон
источник
1
«Некоторые (достаточно современные!) файловые системы ограничены 32000 записей в одном каталоге». Если это самое строгое ограничение, которое встречает Git, то не лучше ли для Git использовать первые три символа хеша вместо первых двух ? Это будет означать, что objectsкаталог может содержать до 4096 подкаталогов вместо ограниченного 256, что отвечает вышеупомянутому требованию, но с дополнительным преимуществом, что эти подкаталоги будут в 16 раз менее вероятно содержать в себе> 32000 файлов.
Сампаблокупер
1

Эти 256 блоков позволяют git хранить большие репозитории в файловых системах, которые ограничивают количество файлов в каталоге и обеспечивают низкую производительность в файловых системах, которые снижаются при использовании каталогов, содержащих много файлов.

Каспер ван ден Берг
источник
1

Существуют некоторые реализации файловых систем и / или файловых систем и / или реализаций libc, в которых производительность снижается при большом количестве записей каталога.

Йорг Миттаг
источник