1000000 개의 작은 파일 복사 속도 향상 디렉토리에 1000000

디렉토리에 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여러 파일 인수를 취할 수있는 것보다 사용 속도가 훨씬 빠릅니다 . hdparm1,000,000 번 실행하는 오버 헤드 만으로도 많은 오버 헤드가 발생합니다.

또한 각 파일에 대해 perl스크립트 (또는 C 프로그램)를 FIEMAP ioctl작성하고 복사 해야하는 블록과 정렬 된 블록의 정렬 된 배열을 만든 다음 모든 것을 순서대로 복사하는 것이 어렵지 않을 것입니다. 해당 파일에서 각 블록의 크기를 읽습니다 (파일 설명자가 부족하지 않도록주의하십시오).


답변