[performance] git 상태 성능을 개선하는 방법

NFS에있는 Linux 시스템에 10GB의 저장소가 있습니다. 처음 git status에는 36 분이 git status걸리고 그 다음에 는 8 분이 걸립니다. Git은 파일 캐싱을 위해 OS에 의존하는 것 같습니다. 첫 번째 git명령은 좋아 commit, status그 / 팩을 포함 전체의 repo 거대한 환매 특약을 위해 매우 오랜 시간이 걸립니다 재 포장. git status그렇게 큰 저장소를 사용했는지 확실하지 않지만이 문제를 겪은 사람이 있습니까?

나는 시도 git gc, git clean, git repack하지만 걸리는 시간은 여전히 / 거의 같은.

하위 모듈이나 저장소를 더 작은 것으로 나누는 것과 같은 다른 개념이 도움이 될까요? 그렇다면 더 큰 저장소를 분할하는 것이 가장 좋습니다. 큰 저장소에서 git 명령에 걸리는 시간을 개선하는 다른 방법이 있습니까?



답변

더 정확하게 말하면 git은 lstat(2)시스템 호출 의 효율성에 의존 하므로 클라이언트의 “attribute cache timeout”을 조정 하면 트릭이 될 수 있습니다.

에 대한 매뉴얼 ( git-update-index기본적으로 수동 모드) 플래그사용하여 정상적인 동작을 억제하고 변경 한 경로를 수동으로 업데이트 git-status함으로써이를 완화하기 위해 수행 할 수있는 작업을 설명합니다 . 파일을 저장할 때마다이 플래그를 설정 해제하도록 편집기를 프로그래밍 할 수도 있습니다.--assume-unchanged

당신이 제안한 대안은 체크 아웃의 크기를 줄이는 것입니다 (팩 파일의 크기는 여기서 실제로 작동하지 않습니다). 옵션은 스파 스 체크 아웃, 하위 모듈 또는 Google의 저장소 도구입니다.

( NFS와 함께 Git을 사용하는 것에 대한 메일 링리스트 스레드가 있지만 많은 질문에 대답하지 않습니다.)


답변

NFS를 통해 공유되는 대규모 프로젝트에서도이 문제가 발생합니다.

git commit과 git status 모두에 제공 할 수있는 플래그 -uno 를 발견하는 데 시간이 좀 걸렸습니다 .

이 플래그가하는 일은 추적되지 않는 파일 찾기를 비활성화하는 것입니다. 이렇게하면 nfs 작업 수가 크게 줄어 듭니다. 그 이유는 git이 추적되지 않은 파일을 발견하려면 모든 하위 디렉터리를 찾아야하므로 하위 디렉터리가 많으면 해를 입힐 수 있습니다. 추적되지 않는 파일을 찾지 못하도록 git을 비활성화하면 이러한 모든 NFS 작업이 제거됩니다.

이것을 core.preloadindex 플래그와 결합하면 NFS에서도 공감할 수있는 성능을 얻을 수 있습니다.


답변

git gc 사용해보십시오 . 또한 git clean 도움이 수 있습니다.

업데이트 -반대표가 어디서 왔는지 확실하지 않지만 git 매뉴얼에는 구체적으로 다음과 같이 명시되어 있습니다.

파일 개정을 압축 (디스크 공간을 줄이고 성능을 높이기 위해 )하고 이전에 git add를 호출하여 생성되었을 수있는 도달 할 수없는 객체를 제거하는 등 현재 저장소 내에서 여러 가지 관리 작업을 실행합니다 .

사용자는 각 저장소 내에서이 작업을 정기적으로 실행하여 좋은 디스크 공간 활용도와 우수한 운영 성능을 유지하는 것이 좋습니다.

git 상태가 느릴 때 git gc를 실행 한 후 항상 차이가 있습니다!

업데이트 II- 내가 이것을 어떻게 놓쳤는 지 확실하지 않지만 OP는 이미 시도 git gc하고 git clean. 나는 그것이 원래 거기에 없었 음을 맹세하지만 편집에 어떤 변화도 보이지 않습니다. 그 죄송합니다!


답변

git 저장소가 하위 모듈을 많이 사용하는 경우 .git 디렉토리의 구성 파일을 편집하고 ignore = dirty특히 크거나 무거운 하위 모듈을 설정 하여 git 상태의 성능을 크게 높일 수 있습니다 . 예를 들면 :

[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty

잊었을 수있는 하위 모듈에 단계적이지 않은 변경 사항이 있다는 알림의 편의를 잃게되지만 하위 모듈이 주 저장소와 동기화되지 않은 경우를 아는 주된 편의는 여전히 유지됩니다. 또한 작업 디렉토리를 하위 모듈 자체로 변경하고 평소와 같이 git status를 사용하여 더 많은 정보를 볼 수 있습니다. 참조 이 질문에 무엇을 “더러운”수단에 대한 자세한 내용을.


답변

Git 상태의 성능은 Git 2.13 (2017 년 2 분기)에서 개선 될 것입니다.

Jeff Hostetler ( )의 commit 950a234 (2017 년 4 월 14 일)를 참조하십시오 . (Merged by Junio ​​C Hamano in commit 8b6bba6 , 24 Apr 2017)jeffhostetler
gitster

> string-list: 재 할당시 ALLOC_GROW매크로 사용string_list

배열을 ALLOC_GROW()재 할당 할 때 string_list단순히 32만큼 늘리기보다는 매크로를 사용하십시오 .
이것은 성능 최적화입니다.

매우 큰 리포지토리의 상태와 많은 변경 사항이있는 동안 총 실행 시간의 상당 부분이 wt_status.changes어레이를 재 할당하는 데 소비 됩니다 .

이 변경으로 wt_status_collect_changes_worktree()매우 큰 저장소에서 시간이 125 초에서 45 초로 단축됩니다.


또한 Git 2.17 (2018 년 2 분기)은 인덱스가 많은 작업에서 시간이 소비되는 위치를 측정하기위한 새로운 추적을 도입합니다.

Nguyễn Thái Ngọc Duy ( )의 commit ca54d9b (2018 년 1 월 27 일)를 참조하십시오 . (Merged by Junio ​​C Hamano in commit 090dbea , 15 Feb 2018)pclouds
gitster

trace: 인덱스가 많은 작업에서 시간이 소요되는 위치 측정

알려진 모든 무거운 코드 블록이 측정됩니다 (객체 데이터베이스 액세스 제외). 이는 최적화가 효과적인지 여부를 식별하는 데 도움이됩니다.
최적화되지 않은 git-status는 다음과 같습니다.

0.001791141 s: read cache ...
0.004011363 s: preload index
0.000516161 s: refresh index
0.003139257 s: git command: ... 'status' '--porcelain=2'
0.006788129 s: diff-files
0.002090267 s: diff-index
0.001885735 s: initialize name hash
0.032013138 s: read directory
0.051781209 s: git command: './git' 'status'

동일한 Git 2.17 (2018 년 2 분기)이 다음 git status과 같이 개선 되었습니다.

revision.c: 개체 데이터베이스 쿼리 줄이기

에서는 mark_parents_uninteresting()커밋을 파싱 된 것으로 처리해야하는지 확인하기 위해 객체 파일이 있는지 확인합니다. 결과는 커밋에 “파싱 된”비트를 설정하는 것입니다.

has_object_file()결과가 구문 분석 된 비트를 변경 하는지 확인하도록 조건을 수정하십시오 .

로컬 브랜치가 업스트림 참조와 다른 경우 ” git status“는 앞 / 뒤 카운트를 계산합니다.
이것은 사용 paint_down_to_common()하고 mark_parents_uninteresting().

origin/master~ 60,000 개 커밋에 의해 원격 브랜치 “”뒤에 “master”의 로컬 인스턴스가있는 Linux 리포지토리의 복사본에서 ” “의 성능이 git status1.42 초에서 1.32 초로, 상대적 차이는 -7.0 %로 떨어졌습니다.


Git 2.24 (2019 년 3 분기)는 git status성능 향상을위한 또 다른 설정을 제안 합니다.

참조 aaf633c 커밋 , c6cc4c5 커밋 , ad0fb65 커밋 , 31b1de6 커밋 , b068d9a 커밋 , 7211b9e 커밋 에 의해 (2019년 8월 13일) 데릭 Stolee을 ( derrickstolee) .
(Merged by Junio ​​C gitsterHamano in commit f4f8dfe , 09 Sep 2019)

repo-settings : feature.manyFiles 설정 생성

feature.manyFiles설정은 작업 디렉토리에 많은 파일이있는 저장소에 적합합니다. 및
을 설정 하면 ‘ ‘ 와 같은 명령 이 향상됩니다.index.version=4core.untrackedCache=truegit status

그러나:

Git 2.24 (2019 년 4 분기)에서 index.version구성 을 읽는 코드 경로 가 수정 된 최근 업데이트로 인해 손상되었습니다.

Derrick Stolee ( )의 commit c11e996 (2019 년 10 월 23 일)을 참조하십시오 . (Merged by Junio ​​C Hamano in commit 4d6fb2b , 24 Oct 2019)derrickstolee
gitster

repo-settings: index.version에 대한 int 읽기

서명자 : Derrick Stolee

7211b9e ( ” : 일부 구성 설정 통합”, 2019-08-13, Git v2.24.0-rc1 repo_settings에서 “index.version”구성 설정 이동 포함) 여러 구성 옵션이 ds / feature-macros 의 구조체 로 결합되었습니다. – 일괄 # 0에 나열된 병합 ).repo-settings

불행하게도, 그 파일은 상용구의 많은처럼 보였다과 무슨 일이 명확하게 구성 설정과 구문 분석 복사 – 붙여 넣기 과부하의 요소입니다 repo_config_ge_bool()대신 repo_config_get_int(). 즉, “index.version = 4″설정이 올바르게 등록되지 않고 기본 버전 인 3으로 되돌아갑니다.

v2.24.0-rc0을 Git 코드베이스 용 VFS에 통합하는 동안이 문제를 포착했습니다. 여기서 색인이 버전 4에 있다는 사실을 정말 신경 씁니다.

버전 검사 t1600-index.sh가 “기본”시나리오를 충분히 테스트하지 않았기 때문에 이것은 코드베이스에 의해 포착 되지 않았습니다. 여기서는 features.manyFiles또는에 의해 재정의되지 않도록 이러한 일반 설정을 포함하도록 테스트를 수정합니다 GIT_INDEX_VERSION.
“기본”버전은 3이지만 do_write_index()필요하지 않은 경우 버전 2로 강등됩니다 .


답변

git config --global core.preloadIndex true

나를 위해 일했다. 여기 에서 공식 문서를 확인 하십시오 .


답변

20-30 개의 서브 모듈 범위에있는 코드베이스에서
git status --ignore-submodules
저를 위해 엄청난 속도를 냈습니다. 이것은 하위 모듈의 상태에 대해보고하지 않습니다. .