Git은 100,000 개의 개체에 대해 정말 느립니다. 수정 사항이 있습니까?
100,000 개 이상의 개체가있는 "신선한"git-svn 리포지토리 (11.13GB)가 있습니다.
나는 미리 형성했다
git fsck
git gc
초기 체크 아웃 후 저장소에 있습니다.
그런 다음
git status
git 상태를 수행하는 데 걸리는 시간은 2m25.578s 및 2m53.901s입니다.
명령을 실행하여 자식 상태를 테스트했습니다.
time git status
5 번, 모든 시간이 위에 나열된 두 시간 사이에 실행되었습니다.
VM을 통하지 않고 로컬로 Mac OS X에서이 작업을 수행하고 있습니다.
이렇게 오래 걸릴 리가 없습니다.
어떤 아이디어? 도움?
감사.
편집하다
내 옆에 비슷한 상자를 들고있는 동료가 있습니다. 더 적은 RAM과 jfs 파일 시스템으로 데비안 실행. 그의 git 상태 는 동일한 repo에서 .3으로 실행됩니다 (또한 git-svn 체크 아웃 임).
또한 최근에이 폴더에 대한 파일 권한 (777)을 변경하여 시간이 상당히 단축되었습니다 (왜, 단서가 없습니다). 이제 3 초에서 6 초 사이 어디에서나 완료 할 수 있습니다. 이것은 관리 할 수 있지만 여전히 고통입니다.
바로 지금 볼 수있는 몇 가지 항목이 있습니다.
git gc --aggressive
- 파일 권한 열기
777
뭔가 다른 일이 일어나야하는데 이것이 가장 큰 영향을 준 것은 분명한 일이었습니다.
git status는 매번 저장소의 모든 파일을 확인해야합니다. 작업하지 않는 나무를 보지 말라고 말할 수 있습니다.
git update-index --assume-unchanged <trees to skip>
맨 페이지에서 :
이러한 플래그를 지정하면 경로에 대해 기록 된 개체 이름이 업데이트되지 않습니다. 대신 이러한 옵션은 경로에 대해 "변경되지 않은 것으로 가정"비트를 설정 및 설정 해제합니다. "변경되지 않은 것으로 가정"비트가 켜져 있으면 git은 작업 트리 파일의 가능한 수정 확인을 중지하므로 작업 트리 파일을 변경할 때 git에 알리려면 비트를 수동으로 설정 해제해야합니다. 이것은 lstat (2) 시스템 호출 (예 : cifs)이 매우 느린 파일 시스템에서 큰 프로젝트로 작업 할 때 때때로 유용합니다.
이 옵션은 추적 된 파일에서 커밋되지 않은 변경 사항을 무시하는 대략적인 파일 수준 메커니즘으로도 사용할 수 있습니다 (추적되지 않은 파일에 대해 .gitignore가 수행하는 작업과 유사 함). Git은 예를 들어 커밋에서 병합 할 때 색인에서이 파일을 수정해야하는 경우 (정상적으로) 실패합니다. 따라서 추적되지 않은 것으로 가정 된 파일이 업스트림으로 변경되는 경우 상황을 수동으로 처리해야합니다.
git의 많은 작업은 효율적인 lstat (2) 구현을 위해 파일 시스템에 의존하므로 작업 트리 파일에 대한 st_mtime 정보를 저렴하게 확인하여 파일 내용이 인덱스 파일에 기록 된 버전에서 변경되었는지 확인할 수 있습니다. 불행히도 일부 파일 시스템에는 비효율적 인 lstat (2)가 있습니다. 파일 시스템이 그 중 하나 인 경우 변경하지 않은 경로에 "변경되지 않은 것으로 가정"비트를 설정하여 git이이 검사를 수행하지 않도록 할 수 있습니다. 경로에이 비트를 설정한다고해서 git이 파일의 내용을 확인하여 변경되었는지 확인하는 것은 아닙니다. 확인을 생략하고 변경되지 않았다고 가정합니다. 작업 트리 파일을 변경할 때 수정 전이나 후에 "변경되지 않은 것으로 가정"비트를 삭제하여 git에게 명시 적으로 알려야합니다.
...
"변경되지 않은 것으로 가정"비트를 설정하려면 --assume-unchanged 옵션을 사용하십시오. 설정을 해제하려면 --no-assume-unchanged를 사용하십시오.
이 명령은 core.ignorestat 구성 변수를 확인합니다. 이것이 사실이면 경로는 git update-index 경로로 업데이트되고 ... 경로는 색인과 작업 트리를 모두 업데이트하는 다른 git 명령으로 업데이트됩니다 (예 : git apply --index, git checkout-index -u 및 git read-tree -u )는 자동으로 "변경되지 않은 것으로 가정"으로 표시됩니다. git update-index --refresh가 작업 트리 파일이 색인과 일치하는 것을 발견하면 "변경되지 않은 것으로 가정"비트가 설정되지 않습니다 ( "변경되지 않은 것으로 가정"으로 표시하려면 git update-index --really-refresh 사용).
이제 분명히이 솔루션은 편리하게 무시할 수있는 저장소의 일부가있는 경우에만 작동합니다. 비슷한 크기의 프로젝트를 작업하고 있는데 정기적으로 확인할 필요가없는 큰 나무가 분명히 있습니다. git-status의 의미는 일반적으로 O (n) 문제 (파일 수 n)를 만듭니다. 그보다 더 잘하려면 도메인 별 최적화가 필요합니다.
스티칭 패턴으로 작업하는 경우, 즉 리베이스 대신 병합을 통해 업스트림의 변경 사항을 통합하는 경우 업스트림에서 병합되는 변경되지 않은 --assume-unchanged 객체의 변경 사항이 병합이되기 때문에이 솔루션은 덜 편리해집니다. 충돌. 리베이스 워크 플로우를 통해이 문제를 피할 수 있습니다.
git status
Git 2.13 (2017 년 2 분기)에서는 다음과 같은 이유로 더 빠릅니다.
- 문자열 최적화 배열에 대한 최적화 ( " 성능 향상 방법
git status
"참조 ) - 더 나은 "읽기 캐시"관리.
마지막 지점에서 Jeff Hostetler ( )의 commit a33fc72 (2017 년 4 월 14 일)를 참조하세요 . (Merged by Junio C Hamano -- in commit cdfe138 , 24 Apr 2017)jeffhostetler
gitster
read-cache
:force_verify_index_checksum
" "전역 변수가 설정 되지 않은 경우에서
verify_hdr()
호출되는 색인 파일의 끝에서 SHA1-1 체크섬 확인을 건너 뛰도록 git에게 알려 줍니다.read_index()
force_verify_index_checksum
fsck
이 확인을 강제하도록 가르치십시오 .체크섬 확인은 디스크 손상을 감지하기위한 것이며 소규모 프로젝트의 경우 SHA-1을 계산하는 데 걸리는 시간은 그다지 중요하지 않지만 거대한 저장소의 경우이 계산이 모든 명령에 상당한 시간을 추가합니다.
Git 2.14 는 구조 의 필드를 사용하여 데이터가 변경되지 않은 경우 Git이 추적되지 않은 디렉토리 읽기를 건너 뛸 수 있도록 하는 " 추적되지 않은 캐시 " 를 더 잘 고려하여 git 상태 성능을 다시 향상시킵니다 .stat
mtime
stat
Documentation/technical/index-format.txt
추적되지 않은 캐시에 대한 자세한 내용은를 참조하십시오 .
David Turner ( )의 commit edf3b90 (2017 년 5 월 8 일)을 참조하십시오 . (Merged by Junio C Hamano -- in commit fa0624f , 30 May 2017)dturner-tw
gitster
"
git checkout
", "git merge
"등이 인 코어 인덱스를 조작 할 때 인덱스 확장의 다양한 정보는 원래 상태에서 삭제됩니다. 일반적으로 최신 상태로 유지되는 경우가 아니기 때문입니다. 기본 인덱스의 작업과 동기화됩니다.추적되지 않은 캐시 확장은 이제 이러한 작업을 통해 복사되므로 캐시가 제대로 무효화되는 한 "git status"속도가 빨라집니다.
일반적으로 Git 2.14.x / 2.15를 사용하면 캐시에 쓰는 것이 더 빠릅니다.
참조 ce012de 커밋 , b50386c 커밋 , 3921a0b 커밋 에 의해 (2017년 8월 21일) 케빈 Willford를 (``) .
(Merged by Junio C gitster
Hamano -- in commit 030faf2 , 27 Aug 2017)
우리는 각 인덱스 항목을 작성하는 동안 메모리를 할당하고 해제하는 데 필요한주기 이상을 소비했습니다.
이것은 최적화되었습니다.[That]은 작은 저장소에서 성능 저하없이 인덱스에 백만 개 이상의 항목이있는 경우 3-7 % 사이의 비용을 절약 할 수 있습니다.
2017 년 12 월 업데이트 : Git 2.16 (2018 년 1 분기)은 git log
느슨한 개체 파일을 반복하는 코드가 방금 최적화되었으므로 이번에는를위한 추가 개선 사항을 제안합니다 .
Derrick Stolee ( )의 commit 163ee5e (2017 년 12 월 4 일)를 참조하십시오 . (Merged by Junio C Hamano -- in commit 97e1f85 , 13 Dec 2017)derrickstolee
gitster
sha1_file
:strbuf_add()
대신 사용strbuf_addf()
에서 느슨한 개체를 열거 할 때 사용을
strbuf_addf()
로 바꿉니다 . 경로를 사용하기 전에 문자열의 길이와 16 진수 값을 이미 확인 했으므로 하위 수준 방법을 사용하여 추가 계산을 방지 할 수 있습니다.strbuf_add()
for_each_file_in_obj_subdir()
의 한 소비자
for_each_file_in_obj_subdir()
는 약어 코드입니다. OID ( 개체 식별자 ) 약어는 느슨한 개체 (개체 하위 디렉터리 당)의 캐시 된 목록을 사용하여 반복되는 쿼리를 빠르게 수행하지만 느슨한 개체가 많을 때는 상당한 캐시로드 시간이 있습니다.대부분의 리포지토리에는 재 포장하기 전에 느슨한 개체가 많지 않지만 GVFS의 경우 ( " GVFS (Git 가상 파일 시스템) 발표 "참조 ) 저장소 는 수백만 개의 느슨한 개체를 포함하도록 확장 될 수 있습니다. ~ 250 만 개의 느슨한 개체가있는 GVFS 지원 리포지토리의 Git For Windows
에서 'git log'성능을 프로파일 링 하면 CPU 시간의 12 %가 .strbuf_addf()
p4211-line-log.sh
이 캐시 로딩에 더 민감한 새 성능 테스트를 추가하십시오 .
커밋을 1000 개로 제한함으로써 히스토리를 호출기로 읽을 때 사용자 대기 시간과 더 비슷합니다.2 개의 ~ 512MB 팩 파일과 ~ 572K의 느슨한 객체가있는 Linux 저장소 사본의 경우 'git log --oneline --parents --raw -1000'을 실행하면 다음 성능이 나타납니다.
HEAD~1 HEAD
----------------------------------------
7.70(7.15+0.54) 7.44(7.09+0.29) -3.4%
2018 년 3 월 업데이트 : Git 2.17이 git status
더 개선 될 것 입니다. 이 답변을 참조하십시오 .
업데이트 : Git 2.20 (2018 년 4 분기) 은 인덱스를 더 빠르게로드 할 수있는 인덱스 항목 오프셋 테이블 (IEOT)을 추가합니다 git status
.
참조 77ff112 커밋 , 3,255,089 커밋 , abb4bb8 커밋 , c780b9c 커밋 , 3b1d9e0 커밋 , 371ed0d 커밋 에 의해 (2018년 10월 10일) 벤 씩씩한를 ( benpeart
) . Nguyễn Thái Ngọc Duy ( )의 commit 252d079 (2018 년 9 월 26 일)를
참조하십시오 . (Merged by Junio C Hamano -- in commit e27bfaa , 19 Oct 2018)pclouds
gitster
읽기 캐시 : 작업자 스레드에 캐시 항목로드
이 패치는 IEOT (Index Entry Offset Table) 를 사용하여 캐시 항목의로드와 변환을 병렬로 여러 스레드로 나누어 인덱스를로드하는 CPU 비용을 해결하는 데 도움이됩니다 .
내가 사용하는
p0002-read-cache.sh
일부 성능 데이터를 생성합니다 :Test w/100,000 files reduced the time by 32.24% Test w/1,000,000 files reduced the time by -4.77%
1,000,000 개 파일의 경우 캐시 항목 구문 분석을 멀티 스레딩해도 성능이 향상되지는 않습니다. 이는이 저장소에서 인덱스 확장을 구문 분석하는 비용이 캐시 항목을로드하는 비용보다 훨씬 크기 때문입니다.
이를 통해 다음을 수행 할 수 있습니다.
config
: 새index.threads
구성 설정 추가
index.threads
에서 스레딩 코드를 제어하는 데 사용할 새 구성 설정에 대한 지원을 추가합니다do_read_index()
.
- A value of 0 will tell the index code to automatically determine the correct number of threads to use.
A value of 1 will make the code single threaded.- A value greater than 1 will set the maximum number of threads to use.
For testing purposes, this setting can be overwritten by setting the
GIT_TEST_INDEX_THREADS=<n>
environment variable to a value greater than 0.
Git 2.21 (Q1 2019) introduces a new improvement, with the update of the loose object cache, used to optimize existence look-up, which has been updated.
See commit 8be88db (07 Jan 2019), and commit 4cea1ce, commit d4e19e5, commit 0000d65 (06 Jan 2019) by René Scharfe (rscharfe
).
(Merged by Junio C Hamano -- gitster
-- in commit eb8638a, 18 Jan 2019)
object-store
: use oneoid_array
per subdirectory for loose cacheThe loose objects cache is filled one subdirectory at a time as needed.
It is stored in anoid_array
, which has to be resorted after each add operation.
So when querying a wide range of objects, the partially filled array needs to be resorted up to 255 times, which takes over 100 times longer than sorting once.Use one
oid_array
for each subdirectory.
This ensures that entries have to only be sorted a single time.
It also avoids eight binary search steps for each cache lookup as a small bonus.The cache is used for collision checks for the log placeholders
%h
,%t
and%p
, and we can see the change speeding them up in a repository with ca. 100 objects per subdirectory:
$ git count-objects
26733 objects, 68808 kilobytes
Test HEAD^ HEAD
--------------------------------------------------------------------
4205.1: log with %H 0.51(0.47+0.04) 0.51(0.49+0.02) +0.0%
4205.2: log with %h 0.84(0.82+0.02) 0.60(0.57+0.03) -28.6%
4205.3: log with %T 0.53(0.49+0.04) 0.52(0.48+0.03) -1.9%
4205.4: log with %t 0.84(0.80+0.04) 0.60(0.59+0.01) -28.6%
4205.5: log with %P 0.52(0.48+0.03) 0.51(0.50+0.01) -1.9%
4205.6: log with %p 0.85(0.78+0.06) 0.61(0.56+0.05) -28.2%
4205.7: log with %h-%h-%h 0.96(0.92+0.03) 0.69(0.64+0.04) -28.1%
One longer-term solution is to augment git to cache filesystem status internally.
Karsten Blees has done so for msysgit, which dramatically improves performance on Windows. In my experiments, his change has taken the time for "git status" from 25 seconds to 1-2 seconds on my Win7 machine running in a VM.
Karsten's changes: https://github.com/msysgit/git/pull/94
Discussion of the caching approach: https://groups.google.com/forum/#!topic/msysgit/fL_jykUmUNE/discussion
In general my mac is ok with git but if there are a lot of loose objects then it gets very much slower. It seems hfs is not so good with lots of files in a single directory.
git repack -ad
Followed by
git gc --prune=now
Will make a single pack file and remove any loose objects left over. It can take some time to run these.
You could try passing the --aggressive
switch to git gc
and see if that helps:
# this will take a while ...
git gc --aggressive
Also, you could use git filter-branch
to delete old commits and/or files if you have things which you don't need in your history (e.g., old binary files).
For what it's worth, I recently found a large discrepancy beween the git status
command between my master and dev branches.
To cut a long story short, I tracked down the problem to a single 280MB file in the project root directory. It was an accidental checkin of a database dump so it was fine to delete it.
Here's the before and after:
⚡ time git status
# On branch master
nothing to commit (working directory clean)
git status 1.35s user 0.25s system 98% cpu 1.615 total
⚡ rm savedev.sql
⚡ time git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: savedev.sql
#
no changes added to commit (use "git add" and/or "git commit -a")
git status 0.07s user 0.08s system 98% cpu 0.157 total
I have 105,000 objects in store, but it appears that large files are more of a menace than many small files.
You also might try git repack
Maybe you use a virus scanner? I've tested some big projects here on Windows and on Linux - it was damn fast!
I don't think that you need to do a git gc in a cloned repo (it should be clean).
Is your harddrive OK? IOPS and R/W per second? Maybe it is damaged?
maybe spotlight is trying to index the files. Perhaps disable spotlight for your code dir. Check Activity Monitor and see what processes are running.
I'd create a partition using a different file system. HFT+ has always been sluggish for me compared to doing similar operations on other file systems.
Try running Prune command it will get rid off, loose objects
git remote prune origin
ReferenceURL : https://stackoverflow.com/questions/3313908/git-is-really-slow-for-100-000-objects-any-fixes
'programing' 카테고리의 다른 글
메서드에서 열거 형을 로컬로 선언 할 수없는 이유는 무엇입니까? (0) | 2021.01.15 |
---|---|
Eclipse에서 git의 두 개정판을 어떻게 비교할 수 있습니까? (0) | 2021.01.15 |
Java XPath (Apache JAXP 구현) 성능 (0) | 2021.01.15 |
diff의 오류 종료 값은 무엇입니까? (0) | 2021.01.15 |
similar_text는 어떻게 작동합니까? (0) | 2021.01.15 |