내 디렉토리에 1000,000개의 4-20kb 파일이 있습니다(이와 유사한 파일을 생성할 수 있습니다 seq 10000 | gzip > a; seq 1000000 | parallel --bar 'head -c{=$_=int(rand()*16)+4=}k a > {}'
:)
. 이 디렉토리를 복사해야 합니다. 그런데 파일을 일일이 검색해야 하는 것 같아서 시간이 꽤 걸립니다.
속도를 높일 수 있는 방법이 있나요?
현재 이러한 파일이 차지하는 디스크 블록을 얻을 수 있다면 파일을 정렬하고 가까운 블록을 병합하고(순차 읽기가 일반적으로 탐색보다 빠르다는 점을 고려하여) 블록을 읽어서 RAM 캐싱에 포함되도록 할 수 있다고 생각하고 있습니다. 복사본(저는 32GB RAM을 가지고 있습니다).
하지만 이를 달성하려면 파일이 있는 블록을 식별할 수 있는 방법이 필요합니다.
저는 자기 장치(즉, SSD가 아님)에서 EXT4를 사용하고 있습니다.
편집하다:
이는 작동하지만 작동하지 않습니다.
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 속도가 빨라지지 않는다는 통념이 깨졌습니다. 여기에서 명시적이고 일관되게 병렬화하면 복제 속도가 빨라질 수 있습니다.
답변1
우리가 말하면
- 반환된 항목은
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
답변2
tar
전통적으로 GNU는 pax
하드 링크 자체를 처리합니다.
cd "$srcdir" ; tar --hard-dereference -cf - ./* |
tar -C"${tgtdir}" -vxf -
이렇게 하면 두 개의 프로세스만 있고 반복해서 호출 tar
할 필요가 없습니다 .cp
답변3
비슷하게작성자: @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
MMV에는 위의 스크립트가 포함되어 있으므로 sed
철저하게 테스트해 보시기 바랍니다.
그렇지 않으면 무엇을 하든 (의 일부)는 여러 파일 인수를 사용할 수 있는 것보다 훨씬 빠르게 filefrag
사용됩니다 . 1,000,000번 실행하는 오버헤드만으로도 많은 오버헤드가 추가됩니다.e2fsprogs
hdparm
hdparm
perl
또한 FIEMAP
ioctl
각 파일에 대해 복사해야 할 청크와 해당 청크가 속한 파일의 정렬된 배열을 생성한 다음 모든 것을 순서대로 복사하고 각 청크를 읽는 스크립트(또는 C 프로그램)를 작성하는 것은 그리 어렵지 않을 수 있습니다. 해당 파일 크기(단, 파일 설명자가 부족하지 않도록 주의하세요)