Git .git / objects / 폴더가 많은 SHA- 접두사 폴더로 세분화되는 이유는 무엇입니까?


21

Git은 내부적으로 .git/objects/폴더 (객체, 나무)를 폴더에 저장합니다. 각 객체는 객체의 내용에서 계산 된 SHA1 해시로 참조 할 수 있습니다.

그러나 개체는 .git/objects/폴더 안에 직접 저장되지 않습니다 . 대신 각 개체는 SHA1 해시의 접두사로 시작하는 폴더 안에 저장됩니다. 따라서 해시 b7e23ec29af22b0b4e41da31e868d57226121c84가 있는 객체 는.git/objects/b7/e23ec29af22b0b4e41da31e868d57226121c84

Git은 왜 이런 방식으로 객체 스토리지를 세분화합니까?

같은 내가 찾을 수있는 자원, 망할 놈의 내부에있는 페이지 자식 마이크로 컨트롤러에 만 만 설명 하는 방법 이 아닌 이유 .

답변:


33

모든 파일을 하나의 디렉토리에 넣을 수 있지만 때로는 약간 커질 수 있습니다. 많은 파일 시스템에는 한계가 있습니다. git 저장소를 USB 스틱의 FAT32 형식 드라이브에 넣고 싶습니까? 단일 디렉토리에는 65,535 개의 파일 만 저장할 수 있습니다. 즉, 단일 디렉토리를 채울 가능성이 줄어들도록 디렉토리 구조를 세분화해야합니다.

이것은 다른 파일 시스템과 더 큰 자식 저장소에서도 문제가 될 수 있습니다. 상대적으로 작은 자식 저장소 (약 360MiB)와 11k 파일에 대한 181,546 개의 객체가 있습니다. 풀 리눅스의 repo를 당신은 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는 단일 디렉토리에 긴 파일 이름 (8.3 규칙을 준수하지 않는 이름)을 가진 많은 파일을 포함하는 Windows NT 파일 시스템 (NTFS) 형식의 드라이브에서 디렉토리 조작을 수행하는 데 시간이 오래 걸립니다.

NTFS가 디렉토리의 파일을 열거 할 때 긴 파일 이름과 관련된 8.3 이름을 찾아야합니다. NTFS 디렉토리는 정렬 된 상태로 유지되므로 일반적으로 디렉토리 목록에서 해당하는 긴 파일 이름과 8.3 이름은 서로 옆에 있지 않습니다. 따라서 NTFS는 존재하는 모든 파일에 대해 디렉토리의 선형 검색을 사용합니다. 결과적으로 디렉토리 목록을 수행하는 데 필요한 시간은 디렉토리에있는 파일 수의 제곱에 따라 증가합니다. 적은 수의 파일 (수백 미만)의 경우 시간 지연은 무시할 수 있습니다. 그러나 디렉토리의 파일 수가 수천 개로 증가함에 따라 리스팅을 수행하는 데 필요한 시간은 분, 시간 또는 며칠로 늘어날 수 있습니다. 긴 파일 이름이 매우 유사하면 마지막 몇 문자 만 다른 경우 문제가 악화됩니다.

SHA1 체크섬의 이름을 딴 파일을 사용하면 이는 재난과 끔찍한 성능을위한 레시피 일 수 있습니다.

위의 내용은 Windows NT 3.5 (1995 년부터 2000 년대 초까지 일반적으로 사용 된 NTFS 1.2)의 기술 노트에서 나온 것이지만, O (n) 조회가 필요한 링크 된 목록 인 파일 시스템의 구현을 가진 EXT3 과 같은 것들에서도 볼 수 있습니다. . 그리고 B- 트리 변경에도 불구하고 :

HTree 알고리즘은 조회 시간을 크게 향상 시켰지만 readdir ()을 사용하여 큰 디렉토리에있는 모든 파일의 일부 작업을 수행하는 워크로드에 대한 일부 성능 저하를 유발할 수 있습니다.
...
Daniel Phillips와 Andreas Dilger가 제안했지만 아직 구현되지 않은이 성능 문제를 완화 할 수있는 잠재적 인 솔루션 중 하나는 커널이 파일 이름 해시로 inode를 그룹화하는 속성을 가진 inode 번호를 가진 무료 inode를 선택하는 것입니다. Daniel과 Andreas는 디렉토리 크기에 따라 inode 범위에서 inode를 할당 한 다음 파일 이름 해시를 기반으로 해당 범위에서 free inode를 선택하도록 제안합니다. 이론적으로는 디렉토리에서 참조되는 inode에 readdir 순서로 액세스 할 때 발생하는 스 래싱 양을 줄여야합니다. 그러나이 전략이 가속화 될 것이라는 것은 확실하지 않습니다. 실제로 참조해야 할 총 inode 블록 수를 증가시켜 readdir () + stat () 워크로드의 성능을 떨어 뜨릴 수 있습니다. 분명히,

덧붙여서, 성능 향상 방법에 관한이 비트는 2005 년부터 git가 출시 된 해였습니다.

Firefox 및 많은 해시 캐시 파일이있는 다른 많은 응용 프로그램에서 볼 수 있듯이 캐시를 바이트 단위로 분할하는 설계입니다. 성능 비용은 무시할만한 수준이며 구식 시스템과 교차 플랫폼을 사용하는 경우 프로그램 작동의 차이가 될 수 있습니다.


1
인용 한 NTFS 성능 기사가 1994 년에 출시 된 NT 3.5에 적용된다는 것을 알았습니다.
Avner Shahar-Kashtan

1
@ AvnerShahar-Kashtan p. Git은 2005 년에 출시되었습니다. 회사 환경에서 NTFS v1.2 기반 파일 시스템을 2000 년대 초반까지 (기술 회사에서) 사용하고있는 것을 알고 있습니다. git의 요구 사항과 당시 일반적으로 사용 가능한 시스템의 파일 시스템 간에는 반드시 중복되는 부분이 있습니다.

아마도 이것이 git가 도입되었을 때 기술 상태의 역사적 유물이 될 수 있다고 말하면 더 분명 할 것입니다. ) 혼란스러워 보입니다.
Avner Shahar-Kashtan

공정하게 말하면 git'팩'시스템은 이러한 많은 문제를 완화합니다. 이론적 git으로 단일 디렉토리 만 사용하고 해당 디렉토리의 파일 수가 특정 (FS에 따라 다를 수 있음) 제한을 초과하면 재 포장 할 수 있습니다.
nneonneo

5
@ AvnerShahar-Kashtan 링크 된 SO 기사를 읽으면 많은 파일을 포함하는 디렉토리를 처리하는 것이 NT 3.5뿐만 아니라 여러 파일 시스템 및 운영 체제에서 문제가 있음을 알 수 있습니다. 파일 제한은 제쳐두고 파일을 나열하는 것만으로도 많은 오버 헤드가 발생할 수 있습니다.

8

이것이 바람직한 이유는 두 가지입니다.

디렉토리는 임의로 클 수 없습니다. 예를 들어 일부 (합리적으로 현대적인) 파일 시스템은 단일 디렉토리에서 32000 개의 항목으로 제한됩니다. 리눅스 커널에서 커밋의 수는 그 정도입니다. 커밋을 처음 두 16 진수로 세분하면 최상위 크기가 256 개의 항목으로 제한됩니다. 하위 디렉토리는 일반적인 git repos의 경우 훨씬 작습니다.

디렉토리는 선형 적으로 스캔됩니다. 일부 파일 시스템 (예 : Ext * 제품군)에서 디렉토리는 링크 된 목록 또는 항목 테이블입니다. 파일을 찾으려면 일치하는 파일 이름을 찾을 때까지 전체 목록을 스캔합니다. 분명히 이것은 성능에 바람직하지 않습니다. 많은 최신 파일 시스템은 빠른 검색을 위해 해시 테이블 또는 B- 트리를 추가로 사용하지만 모든 사람이이를 가질 수있는 것은 아닙니다. 각 디렉토리를 작게 유지하면 액세스 시간이 단축됩니다.


1
"일부 (합리적으로 현대적인!) 파일 시스템은 단일 디렉토리에서 32000 개의 항목으로 제한됩니다." 그 망할 놈의 회의는 가장 엄격한 제한이 있다면 힘내 처음 사용한 데, 그것은 더 나은되지 않을 것 세 가지 대신에 첫째로, 해시의 문자를 ? 이는 objects디렉토리가 256 개로 제한되는 대신 최대 4096 개의 서브 디렉토리를 보유 할 수 있음을 의미하며 , 위의 요구 사항을 충족하지만, 서브 디렉토리가> 32000 파일 자체를 포함 할 가능성이 16 배 적다는 추가 이점이 있습니다.
sampablokuper

1

이 256 버킷을 사용하면 git은 파일 시스템에 더 큰 리포지토리를 저장하여 디렉토리의 파일 수를 제한하고 많은 파일을 포함하는 디렉토리의 속도가 느려지는 파일 시스템의 성능을 저하시킵니다.


1

많은 디렉토리 항목으로 인해 성능이 저하되는 일부 파일 시스템 및 / 또는 파일 시스템 구현 및 / 또는 libc 구현이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.