tar медленно работает на сервере Ubuntu

У меня есть два сервера (доступ по SSH к Интернету), один с высокопроизводительным процессором и 32 ГБ оперативной памяти. Однако, когда я пытаюсь передать большое количество файлов (около 400 000) с помощью команды:

tar cvf archive.tar folder

Это займет около 2 часов. Когда я выполняю ту же команду на моем компьютере, который имеет аналогичную спецификацию, но меньше оперативной памяти, требуется около 5 минут, чтобы скопировать аналогичный пакет файлов.

У кого-нибудь есть идеи или альтернативы? Командная строка выводит список всех файлов. Я не знаю, вызывает ли это проблемы.

2
задан 7 April 2016 в 02:11

1 ответ

Дисковая фрагментация. Если они - большие файлы, можно использовать filefrag чтобы проверить, насколько фрагментированный отдельные файлы, но существует другой вид фрагментации, которая имеет тенденцию происходить со многими маленькими файлами: порядок, что имена появляются в каталоге, может полностью отличаться от порядка, что inodes появляются на диске, и тот порядок может полностью отличаться от порядка блоков данных на диске. Это означает при открытии всех файлов в порядке, их имена появляются в каталоге, диск должен искать много и замедляет вещи. Я записал следующий сценарий Python однажды для вычислений корреляции между именами, inodes, и первого блока данных всех файлов в текущем каталоге, таким образом, можно измерить это:

#!/usr/bin/python

import os
from stat import *
import fcntl
import array

names = os.listdir('.')
lastino = 0
name_to_ino_in = 0
name_to_ino_out = 0
lastblock = 0
name_to_block_in = 0
name_to_block_out = 0
iblocks = list()
inode_to_block_in = 0
inode_to_block_out = 0

for file in names :
    try :
        st = os.stat(file)
    except OSError:
        continue
    if not S_ISREG(st.st_mode) :
        continue
    if st.st_ino > lastino :
        name_to_ino_in += 1
    else : name_to_ino_out += 1
    lastino = st.st_ino    
    f = open(file)
    buf = array.array('I', [0])
    err = fcntl.ioctl(f.fileno(), 1, buf)
    if err != 0 :
        print "ioctl failed on " + f
    block = buf[0]
    if block != 0 :
        if block > lastblock :
            name_to_block_in += 1
        else : name_to_block_out += 1
        lastblock = block
        iblocks.append((st.st_ino,block))
print "Name to inode correlation: " + str(float(name_to_ino_in) / float((name_to_ino_in + name_to_ino_out)))
print "Name to block correlation: " + str(float(name_to_block_in) / float((name_to_block_in + name_to_block_out)))
iblocks.sort()
lastblock = 0
for i in iblocks:
    if i[1] > lastblock:
        inode_to_block_in += 1
    else: inode_to_block_out += 1
    lastblock = i[1]
print "Inode to block correlation: " + str(float(inode_to_block_in) / float((inode_to_block_in + inode_to_block_out)))

Старые файловые системы, которые имели много маленьких файлов, добавленных за долгое время, имеют тенденцию входить в плохую форму. Просто копирование всего каталога может привести к месту назначения, являющемуся намного лучше, затем можно удалить оригинал и заменить его копией. Вторая проблема, которая способствует этому, хотя три индексированных функции каталога ext4, которые используются на каталогах со многими файлами в них для создания поиска отдельного имени файла намного быстрее, но по существу полностью рандомизируют порядок имен. Можно проверить, использует ли каталог тройки с lsattr -d и ищите I атрибут.

Одна из причин, что я предпочитаю копировать с dump вместо tar это, это неуязвимо для этой проблемы, так как это читает все файлы в порядке inode независимо от порядка, имена появляются в каталоге. Это все еще должно спорить с inode для блокирования фрагментации все же. Копия или передача e2defrag может помочь с этим.

3
ответ дан 7 April 2016 в 12:11

Другие вопросы по тегам:

Похожие вопросы: