디렉토리에 1000000 4-20 kb 파일이 있습니다. 그 디렉토리를 복사해야합니다. 그러나 각 파일을 찾아야하므로 시간이 오래 걸립니다.
속도를 높일 수있는 방법이 있습니까?
나는 현재이 파일들이 차지하는 디스크 블록을 얻을 수 있다면, 그것들을 정렬하고, 가까운 블록을 병합하고 (순차적 읽기가 종종 추구하는 것보다 빠릅니다) 블록을 읽고 RAM에 있도록 할 수 있다고 생각합니다 복사하기 전에 캐시 (32GB RAM이 있음).
그러나 그것이 작동하려면 파일이있는 블록을 식별하는 방법이 필요합니다.
자기 장치에서 EXT4를 사용하고 있습니다 (예 : SSD가 아님).
편집하다:
이것은 작동해야하지만 작동하지 않습니다.
ls |
parallel -IOO --pipe "sudo parallel -j100 hdparm --fibmap {}'|tail -n +5'" |
sort -nk 2 |
perl -ane 'if($u+10000 < $F[1]) { print "$l ",($u-$l),"\n"; $l=$F[1] } $u=$F[2]' |
sudo parallel --colsep ' ' dd if=/dev/sda1 skip={1} bs=512 count={2} '| cat >/dev/null'
큰 파일에서 테스트 할 때는 파일을 캐시하지 않습니다.
편집 2 :
다음은 몇 가지 벤치 마크입니다. echo 3 >/proc/sys/vm/drop_caches
각 실행 사이에 캐시가 플러시되었습니다 ( ). 로 측정 완료 iostats -dkx 5
.
rsync -Hav foo/ bar/: 1800 KB/s
cp -a foo/ bar/: 3600 KB/s
cat sort-by-inode | parallel -j1 -X cp foo/{} bar/: 5000 KB/s
cat sort-by-inode | shuf | parallel -j1 -X cp foo/{} bar/: 3000 KB/s
cat sort-by-inode | shuf | parallel -j10 -X cp foo/{} bar/: 7000 KB/s
cat sort-by-inode | parallel -j10 -X cp foo/{} bar/: 8000 KB/s
cat sort-by-inode | parallel -j100 -X cp foo/{} bar/: 9000 KB/s
cat sort-by-inode | parallel -j500 -X cp foo/{} bar/: 10000 KB/s
그래서 우리는 그로부터 무엇을 배울 수 있습니까?
inode를 기준으로 정렬하는 것이 좋습니다. 그러나 여러 개의 병렬 처리 cp
를 수행하면 성능이 더욱 향상됩니다. 소스 foo/
가 자기 디스크라는 점을 강조 할 가치가 있으므로, I / O를 단일 스핀들로 병렬화하면 I / O 속도가 빨라지지 않는다는 신화를 공격 할 수 있습니다.
답변
그것을 가정
- 에서 반환 한 항목
readdir
은 inode 번호로 정렬되지 않습니다 - inode 순서로 파일을 읽으면 탐색 작업 수가 줄어 듭니다.
- 대부분의 파일의 내용은 초기 8k 할당 (ext4 최적화)에 있으며 탐색 작업이 적습니다.
inode 순서로 파일을 복사하여 복사 속도를 높일 수 있습니다.
이것은 다음과 같은 것을 사용하는 것을 의미합니다.
$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist
답변
GNU tar
-에서 pax
자체 핸들의 하드 링크 – 전통.
cd "$srcdir" ; tar --hard-dereference -cf - ./* |
tar -C"${tgtdir}" -vxf -
이렇게하면 두 개의 tar
프로세스 만 있으며 계속 cp
반복 해서 호출 할 필요가 없습니다 .
답변
@maxschlepzig의 대답 과 비슷한 맥락에서 filefrag
파일의 첫 번째 조각이 디스크에 나타나는 순서대로 출력을 구문 분석 할 수 있습니다 .
find . -maxdepth 1 -type f |
xargs -d'\n' filefrag -v |
sed -n '
/^ 0: 0../ {
s/^.\{28\}\([0-9][0-9]*\).*/\1/
h
}
/ found$/ {
s/:[^:]*$//
H
g
s/\n/ /p
}' |
sort -nk 1,1 |
cut -d' ' -f 2- |
cpio -p dest_dir
위의 sed
스크립트 가 포함 된 MMV 이므로 철저히 테스트하십시오.
그렇지 않으면, 당신이 무엇이든 filefrag
(의 일부 e2fsprogs
) hdparm
여러 파일 인수를 취할 수있는 것보다 사용 속도가 훨씬 빠릅니다 . hdparm
1,000,000 번 실행하는 오버 헤드 만으로도 많은 오버 헤드가 발생합니다.
또한 각 파일에 대해 perl
스크립트 (또는 C 프로그램)를 FIEMAP
ioctl
작성하고 복사 해야하는 블록과 정렬 된 블록의 정렬 된 배열을 만든 다음 모든 것을 순서대로 복사하는 것이 어렵지 않을 것입니다. 해당 파일에서 각 블록의 크기를 읽습니다 (파일 설명자가 부족하지 않도록주의하십시오).