Чому Git .git / об’єкти / папка підрозділяється у багатьох папках префікса SHA?


21

Git внутрішньо зберігає об’єкти (краплі, дерева) у .git/objects/папці. Кожен об'єкт може посилатися на хеш SHA1, який обчислюється із вмісту об'єкта.

Однак об'єкти не зберігаються всередині .git/objects/папки безпосередньо. Натомість кожен об’єкт зберігається всередині папки, яка починається з префікса хеша SHA1. Таким чином, об’єкт із хешем b7e23ec29af22b0b4e41da31e868d57226121c84зберігатиметься в.git/objects/b7/e23ec29af22b0b4e41da31e868d57226121c84

Чому Git таким чином розподіляє сховища об'єктів?

Ресурси, які я міг знайти, як- от сторінка про внутрішні сторінки Git на git-scm, лише пояснювали, як , а не чому .

Відповіді:


33

Можна помістити всі файли в один каталог, хоча іноді це може стати трохи більшим. Багато файлових систем мають обмеження . Ви хочете помістити сховище git на накопичувач формату FAT32 на USB-накопичувач? Ви можете зберігати лише 65 555 файлів в одному каталозі. Це означає, що необхідно підрозділити структуру каталогів так, що заповнення одного каталогу є менш ймовірним.

Це навіть стане проблемою з іншими файловими системами та більшими сховищами git. Відносно невелика ріпо git, яку я розвішувала (близько 360MiB), і вона має 181,546 об’єктів для 11k файлів. Потягніть репо за 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 відповідають властивості, що групує вклади за хешем імені файлу. Даніель і Андреас пропонують виділити inode з діапазону inode залежно від розміру каталогу, а потім вибрати вільний inode з цього діапазону на основі хешу імені файлу. Це теоретично повинно зменшити кількість обмолоту, що виникає при доступі до вхідних кодів, на які посилається каталог, у порядку readdir. Однак не ясно, що ця стратегія призведе до прискорення; насправді це може збільшити загальну кількість блоків inode, на які, можливо, доведеться посилатися, і, таким чином, погіршити продуктивність навантажень readdir () + stat (). Зрозуміло,

До речі, цей біт про те, як покращити продуктивність був з 2005 року, того ж року було випущено git.

Як бачимо з Firefox та багатьма іншими програмами, у яких є безліч хешованих кешованих файлів, розбиття кешу на байт. Він має незначну вартість продуктивності, і при використанні крос-платформи з системами, які можуть бути трохи на старій стороні, цілком може бути різниця між програмою, яка працює чи ні.


1
Ви помітили, що стаття щодо ефективності NTFS, яку ви цитуєте, стосується NT 3.5, випущеного 1994 року, правда?
Авнер Шахар-Каштан

1
@ АвнерШахар-Каштан так. Git був випущений у 2005 році. Я знаю, що я використовував файлові системи на базі NTFS v1.2 у корпоративному середовищі ще на початку 2000-х (тим не менш, у технологічній компанії). Очевидно, що між вимогами git та файловими системами на загальнодоступних системах на той час існує збіг.

Можливо, було б зрозуміліше, якби ви заявили, що це може бути історичним артефактом стану технологій при введенні git, оскільки, як це випливає, для питання, яке було задано у 2015 році, цитуючи двадцятирічне технічне обмеження (прийнявши відповідь ) здається заплутаним.
Авнер Шахар-Каштан

Справедливості, gitсистема "пакування" пом'якшує багато цих питань. Теоретично gitможна використовувати лише один каталог і просто перепакувати, коли кількість файлів у цьому каталозі перевищила певний (можливо FS-залежний) ліміт.
nneonneo

5
@ AvnerShahar-Kashtan, якщо ви прочитаєте пов'язану статтю SO, ви побачите, що працювати з каталогами, що містять велику кількість файлів, проблематично для багатьох файлових систем та операційних систем, а не лише для NT 3.5. Обмеження файлів убік, навіть лише перелік файлів може призвести до великих витрат.

8

Є дві причини, чому це бажано.

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

Каталоги скануються лінійно. У деяких файлових системах (наприклад, сімейство Ext *) каталог є пов'язаним списком або таблицею записів. Щоб шукати файл, весь список сканується, поки не буде знайдено відповідне ім'я файлу. Зрозуміло, що це небажано для виконання. Багато сучасних файлових систем додатково використовують хеш-таблиці або B-дерева для швидкого пошуку, але не у всіх можуть бути такі. Зберігання кожного каталогу невеликим - це швидкий час доступу.


1
"деякі (досить сучасні!) файлові системи обмежені 32000 записами в одному каталозі." Якщо це найсуворіше обмеження, на яке зустрічається Git, то чи не було б краще, щоб Git використовував перші три символи хеша замість перших двох ? Це означає, що objectsкаталог може містити до 4096 підкаталогів, а не обмежуватись 256, задовольняючи вищевикладеній вимозі, але з додатковою перевагою, що ці підкаталоги будуть на 16 разів менше, ніж вони містять> 32000 самих файлів.
sampablokuper

1

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


1

Існують деякі файлові системи та / або реалізації файлової системи та / або реалізації libc, де продуктивність знижується з великою кількістю записів каталогів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.