Tăng tốc độ sao chép 1000000 tệp nhỏ


10

Tôi có 1000000 4-20 kb tệp trong một thư mục. Tôi cần phải sao chép thư mục đó. Nhưng có vẻ như tôi phải thực hiện tìm kiếm cho mỗi tệp nên việc này mất khá nhiều thời gian.

Có cách nào để tôi có thể tăng tốc điều này không?

Hiện tại tôi đang nghĩ rằng nếu tôi có thể lấy được các khối đĩa mà các tệp này chiếm giữ, tôi có thể sắp xếp chúng, hợp nhất các khối gần nhau (với điều kiện là đọc tuần tự thường nhanh hơn tìm kiếm) và đọc các khối này, để chúng nằm trong RAM bộ nhớ cache (tôi có 32 GB RAM) trước khi thực hiện sao chép.

Nhưng để làm việc đó, tôi cần một cách để xác định khối nào được bật.

Tôi đang sử dụng EXT4 trên thiết bị từ tính (không phải SSD).

Biên tập:

Điều này nên hoạt động nhưng nó không:

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'

Khi kiểm tra nó trên một tệp lớn, nó không lưu trữ tệp.

Chỉnh sửa2:

Dưới đây là một số điểm chuẩn. Bộ nhớ cache đã bị xóa ( echo 3 >/proc/sys/vm/drop_caches) giữa mỗi lần chạy. Các phép đo được thực hiện với 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

Vậy chúng ta có thể học được gì từ đó?

Có vẻ như sắp xếp theo inode là một ý tưởng tốt. Nhưng có vẻ như song song nhiều cphiệu suất tăng hơn nữa. Điều đáng nhấn mạnh là nguồn foo/là một đĩa từ tính, do đó, điều này tấn công huyền thoại rằng song song I / O với một trục chính sẽ không tăng tốc I / O: Song song rõ ràng và tăng tốc độ sao chép ở đây.


Có thư mục của bạn chỉ chứa các tập tin? Là vị trí mục tiêu của bạn trên cùng một hệ thống tập tin?
Joseph R.

Đối với lệnh chính xác bạn đang sử dụng để sao chép? Một cái gì đó như cp -r /mnt/dir1 /mnt/dirdesthoặc một cái gì đó như thế cp /mnt/dir1/* /mnt/dirdestnào?
maxschlepzig

Chỉ các tệp nhưng không phải cùng một hệ thống tệp: cp -r / mnt / dir1 / mnt2 / dirdest
Ole Tange

btw, tôi không nghĩ rằng nó hữu ích nếu bạn thực hiện truy cập đĩa cứng song song khi bạn muốn giảm thiểu tìm kiếm đĩa.
maxschlepzig

Tôi đã viết một chương trình đặt hàng các tệp theo số phạm vi của chúng (nhiều khả năng là sự xuất hiện trên đĩa) tại đây: github.com/nh2/diskorder
nh2

Câu trả lời:


9

Giả sử rằng

  • các mục được trả về readdirkhông được sắp xếp theo số inode
  • đọc tệp theo thứ tự inode làm giảm số lượng thao tác tìm kiếm
  • nội dung của hầu hết các tệp nằm trong phân bổ 8k ban đầu (tối ưu hóa ext4) cũng sẽ mang lại ít hoạt động tìm kiếm hơn

bạn có thể cố gắng tăng tốc độ sao chép thông qua sao chép các tập tin theo thứ tự inode.

Điều đó có nghĩa là sử dụng một cái gì đó như thế này:

$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist

@mikeerv, ý bạn là gì? ls -Uvẫn chưa đủ bởi vì nó không sắp xếp theo số inode ... và tại sao tôi lại muốn -1?
maxschlepzig

@mikeerv, 'theo thứ tự thư mục' không giống với thứ tự inode! Nếu đây là trường hợp bạn sẽ không phải sử dụng một từ khác cho việc này. Những gì bạn thấy lạ không liên quan. Tôi thậm chí đã thử nghiệm nó trên một hệ thống tập tin ext4. Và thứ tự thư mục thực sự khác với thứ tự inode. -1chỉ liệt kê 'một tệp trên mỗi dòng' - nó không giúp gì cho dòng mới trong tên tệp. Cho rằng bạn có thể sử dụng find -print0/xargs -O.
maxschlepzig

@mikeerv, bạn đang nói về cái gì vậy? Ví dụ về bộ đếm: mkdir tmp; cd tmp; touch foo"<RETURN>"bar; lsin 'foo? Bar'. A ls -1cũng in 'foo? Bar'. Một ls -1 | wc -lbản in '2'. A find -lsin tên tệp là './foo\nbar'. Một cp -i ls -1` x` thất bại với 'cp: target' x 'không phải là một thư mục'.
maxschlepzig

Chết tiệt - bạn đang dạy tôi trái và phải! -qlàm những gì tôi nghĩ -1sẽ! Một lần nữa, lời xin lỗi của tôi - không đề cập đến cảm ơn.
mikeerv

4

GNU tar- theo paxtruyền thống - tự xử lý các liên kết cứng.

cd "$srcdir" ; tar --hard-dereference -cf - ./* |
    tar -C"${tgtdir}" -vxf -

Bằng cách đó, bạn chỉ có hai tarquy trình và bạn không cần phải cplặp đi lặp lại nhiều lần.


2

Theo cách tương tự với câu trả lời của @ maxschlepzig , bạn có thể phân tích đầu ra filefragđể sắp xếp các tệp theo thứ tự các đoạn đầu tiên của chúng xuất hiện trên đĩa:

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 với sedkịch bản trên , vì vậy hãy chắc chắn kiểm tra kỹ lưỡng.

Mặt khác, bất cứ điều gì bạn làm, filefrag(một phần e2fsprogs) sẽ sử dụng nhanh hơn nhiều so với việc hdparmnó có thể lấy nhiều đối số tệp. Chỉ cần chi phí hoạt động hdparm1.000.000 lần là sẽ có thêm rất nhiều chi phí.

Ngoài ra, có thể sẽ rất khó để viết một perltập lệnh (hoặc chương trình C), FIEMAP ioctlcho mỗi tệp, tạo một mảng được sắp xếp của các khối sẽ được sao chép và các tệp thuộc về và sau đó sao chép mọi thứ theo thứ tự đọc kích thước của mỗi khối từ tệp tương ứng (hãy cẩn thận để không chạy ra khỏi phần mô tả tệp).


Điều này thật tuyệt, xem thêm home.ifi.uio.no/paalh/publications/files/ipccc09.pdf để biết một bài viết mô tả cách tiếp cận và hiển thị tốc độ ~ 4x tarcho các tệp của họ.
nh2

1
Tôi đã gửi email cho các tác giả của bài báo, hỏi liệu họ có thể phát hành qtardưới dạng nguồn mở hay không; bây giờ là tại github.com/chlunde/qtar
nh2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.