1000000 küçük dosyayı kopyalamayı hızlandırın


11

Bir dizin 1000000 4-20 kb dosyaları var. O dizini kopyalamam gerek. Ama her dosya için bir arama yapmak zorunda gibi görünüyor bu yüzden bu biraz zaman alır.

Bunu hızlandırabileceğim bir yol var mı?

Şu anda bu dosyaların kapladığı disk bloklarını alabilirsem, bunları sıralayabilir, yakın olan blokları birleştirebilirim (sıralı okumanın genellikle aramaktan daha hızlı olduğu göz önüne alındığında) ve bu blokları okuyabilirim, böylece RAM'daydılar kopyalamadan önce önbellek (32 GB RAM'im var).

Ancak bunun çalışması için dosyaların hangi bloklarda olduğunu tanımlamanın bir yoluna ihtiyacım var.

Manyetik bir cihazda EXT4 kullanıyorum (yani SSD değil).

Düzenle:

Bu işe yaramalı ama işe yaramıyor:

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'

Büyük bir dosyada test ederken dosyayı önbelleğe almaz.

Edit2:

İşte bazı kriterler. echo 3 >/proc/sys/vm/drop_cachesHer çalışma arasında önbellek temizlendi ( ). Ölçümler ile yapılır 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

Peki bundan ne öğrenebiliriz?

Inode göre sıralama iyi bir fikir gibi görünüyor. Ancak, çoklu destek cpperformansını daha da paralel hale getirmek gibi görünüyor . Kaynağın foo/manyetik bir disk olduğunu vurgulamakta fayda var.


Dizininiz yalnızca dosya içeriyor mu? Hedef konumunuz aynı dosya sisteminde mi?
Joseph R.13

Kopyalama için tam komut mu kullanıyorsunuz? Gibi bir cp -r /mnt/dir1 /mnt/dirdestşey ya da benzeri bir şey cp /mnt/dir1/* /mnt/dirdest?
maxschlepzig

Sadece dosyalar ama aynı dosya sistemi değil: cp -r / mnt / dir1 / mnt2 / dirdest
Ole Tange

btw, disk aramaları en aza indirmek istediğinizde sabit disk erişimlerini paralel olarak çalıştırmanızın yardımcı olacağını düşünmüyorum.
maxschlepzig

Dosyalarını sayı numaralarına göre sipariş eden bir program yazdım (diskte olma olasılığı daha yüksektir): github.com/nh2/diskorder
nh2

Yanıtlar:


9

Varsayalım

  • tarafından döndürülen girdiler readdirinode numarasına göre sıralanmaz
  • dosyaları inode sırayla okumak arama işlemi sayısını azaltır
  • çoğu dosyanın içeriği ilk 8k ayırmadadır (ext4 optimizasyonu) ve bu da daha az arama işlemi sağlar

dosyaları inode sırasıyla kopyalayarak kopyalamayı hızlandırmayı deneyebilirsiniz.

Bu, şöyle bir şey kullanmak anlamına gelir:

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

@mikeserv, ne demek istiyorsun? ls -Uyeterli değil çünkü inode numaralarına göre sıralanmıyor ... ve neden istemeliyim -1?
maxschlepzig

@mikeserv, 'dizin sıralamasında' inode sırasıyla aynı değil! Bu durumda, bunun için farklı bir kelime kullanmanız gerekmez. Tuhaf bulduğun şey alakalı değil. Hatta bir ext4 dosya sisteminde test ettim. Ve orada dizin sırası gerçekten inode sırasından farklıdır. -1sadece 'satır başına bir dosya' listeler - dosya adlarındaki yeni satırlara yardımcı olmaz. Bunun için kullanabilirsiniz find -print0/xargs -O.
maxschlepzig

@mikeserv, neden bahsediyorsun? Sayaç örneği: mkdir tmp; cd tmp; touch foo"<RETURN>"bar; ls'foo? Bar' yazdırır. A ls -1ayrıca 'foo? Bar' yazdırır. A ls -1 | wc -l'2' yazdırır. A find -ls, dosya adını './foo\nbar' olarak yazdırır. Bir cp -i ls -1 `x` 'cp: target' x 'bir dizin değildir' ile başarısız olur.
maxschlepzig

Lanet olsun - bana sağ ve sol öğretiyorsun! -qdüşündüğüm şeyi yapar -1! Tekrar, özür dilerim - teşekkür etmiyorum.
mikeserv

4

GNU tar- paxgelenekte - hardlinkleri kendi başına halleder.

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

Bu şekilde yalnızca iki tarişleme sahip olursunuz cpve tekrar tekrar çağırmaya devam etmenize gerek kalmaz .


2

@ Maxschlepzig'in cevabına benzer bir şekilde , filefragdosyaları ilk parçalarının diskte göründüğü sırayla sıralamak için çıktıyı ayrıştırabilirsiniz :

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

Yukarıdaki sedkomut dosyasıyla MMV , bu yüzden iyice test ettiğinizden emin olun.

Aksi takdirde, ne yaparsanız yapın filefrag(bir kısmı e2fsprogs) kullanmak hdparmbirden fazla dosya argümanı alabileceğinden çok daha hızlı olacaktır . Sadece hdparm1.000.000 kez koşma yükü çok fazla yük ekleyecek.

Ayrıca, bir perlkomut dosyası (veya C programı) yazmak , FIEMAP ioctlher bir dosyaya bir kopyalamak, kopyalanması gereken blokların ve ait olduğu dosyaların sıralı bir dizisini oluşturmak ve daha sonra her şeyi sırayla kopyalamak çok zor olmazdı her bir bloğun boyutunu ilgili dosyadan okuma (yine de dosya tanımlayıcılarının bitmemesine dikkat edin).


Bu güzel, yaklaşımı tanımlayan ve dosyaları için ~ 4x hızlanma gösteren bir makale için home.ifi.uio.no/paalh/publications/files/ipccc09.pdf adresine bakın tar.
nh2

1
Makalenin yazarlarına e-posta gönderdim ve qtaraçık kaynak olarak yayınlayıp yayınlayamayacaklarını sordum ; şimdi github.com/chlunde/qtar
nh2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.