Как обмен может быть таким медленным?

79

Каким-то образом у меня получилось поменять 14 ГБ памяти. После того, как я убил преступника, у меня снова есть тонны свободной памяти, поэтому я подумал, что смогу снова внести важные данные . Итак, из 5 ГБ из 32 ГБ использованных и 14 ГБ пространства подкачки я запустился swapoff -a.... и через 4 часа примерно половина работы была завершена.

Это означает менее 1 МБ / с, в то время как я могу легко скопировать 200 МБ / с. Мой своп зашифрован, но все обычные разделы тоже, и с помощью aes-ni это не приводит к заметной загрузке процессора (а заполнение пространства подкачки заняло всего несколько минут) Я вижу, что нет особой причины для оптимизации swapoff, однако мне интересно, как это могло быть так медленно?


Просто добавьте еще немного данных: моя основная память составляет 32 ГБ, и у меня есть 32 ГБ подкачки на каждом из 4 жестких дисков (конечно, излишнее количество, но кого это волнует?). Все пространство подкачки может быть прочитано (расшифровано и) менее чем за 5 минут:

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

Чтение части раздела не может быть медленнее, чем чтение всего этого. Тем не менее, чтение примерно 1/10 занимает около 100 раз дольше.

Я заметил, что во время swapoffобоих процессоров в основном простаивали (возможно, 10% от одного ядра), как и диски («измеряемые» светодиодами). Я также видел, что места подкачки были выключены один за другим.

maaartinus
источник
1
Интересно, происходит ли такое же явление, когда система сама загружает подкачанные страницы обратно в оперативную память? Например, если система была приостановлена ​​на диск и затем запущена, все было выгружено и загружено обратно в ОЗУ. Кажется, очень медленно для меня тоже.
Петр Пудлак
Все ли swap-устройства активированы с одинаковым приоритетом?
Нильс
@Petr Pudlák: Suspend на диск немного отличается, он просто записывает содержимое RAM в свободное место в области подкачки, и это (и не приостановка), вероятно, намного быстрее. Я не могу попробовать, так как он не работает с зашифрованным свопом.
Maaartinus
@Nils: Да, приоритет такой же, как и у диска и его разбиения.
Maaartinus
Это делает это более странным. В этом случае своп чередуется на всех дисках - это должно быть очень быстро. iostat -d 5Показывал ли низкий IO на дисках во время swapoffтоже?
Нильс

Ответы:

53

Сначала давайте посмотрим, что вы можете ожидать от своего жесткого диска. Ваш жесткий диск может делать 200 МБ / с последовательно . Когда вы учитываете время поиска, оно может быть намного медленнее. Чтобы выбрать произвольный пример, взгляните на спецификации одного из современных 3-ТБ дисков Seagate, ST3000DM001 :

  • Максимальная поддерживаемая скорость передачи данных: 210 МБ / с

  • Ищите среднее чтение: <8,5 мс

  • Байт на сектор: 4 096

Если вам не нужно искать, и если ваш своп находится рядом с краем диска, вы можете ожидать, что максимальная скорость будет равна 210 МБ / с.

Но если ваши данные подкачки полностью фрагментированы, в худшем случае вам нужно будет искать каждый сектор, который вы читаете. Это означает, что вы можете читать только 4 КБ каждые 8,5 мс, или 4 КБ / 0,0085 = 470 КБ / с.

Так что сразу же, это не исключено, что вы на самом деле работает на скорости жесткого диска.


Тем не менее, кажется глупым, что он swapoffбудет работать так медленно и должен читать страницы не по порядку, особенно если они написаны быстро (что подразумевает упорядоченность). Но это может быть просто, как работает ядро. В сообщении об ошибке в Ubuntu # 486666 обсуждается та же проблема:

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

Один из ответов был:

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

Отчет об ошибке был закрыт неразрешенным.

Книга Мела Гормана « Понимание диспетчера виртуальной памяти Linux » немного устарела, но соглашается, что это медленная операция:

Функция, ответственная за деактивацию области, как и ожидалось, вызывается sys_swapoff(). Эта функция в основном связана с обновлением swap_info_struct. Основная задача подкачки на каждой выгружаемой странице состоит в том, ответственность за try_to_unuse()которую чрезвычайно дорога.

В 2007 году было немного больше дискуссий по списку рассылки ядра Linux с темой « ускорение обмена » - хотя обсуждаемые скорости здесь немного выше, чем вы видите.


Это интересный вопрос, который, вероятно, вообще игнорируется, поскольку swapoffиспользуется редко. Я думаю , что если вы действительно хотите , чтобы отслеживать его вниз, первый шаг будет пытаться более тщательно следить за свои дисковые модели использования (возможно , с atop, iostatили даже более мощные инструменты , такие как perfили systemtap). Возможными поисками могут быть чрезмерный поиск, небольшие операции ввода-вывода, постоянное переписывание и перемещение данных и т. Д.

Джим Пэрис
источник
5
Отличное объяснение. Следует отметить, что можно обойти большую часть фрагментации и быстро освободить большую часть подкачки, выполнив дамп
Brandon DuPree
1
Это не просто время фрагментации / поиска. У меня своп на SSD, и случайное чтение происходит очень быстро, но команда swapoff работает намного медленнее, чем нужно, и моя загрузка SSD составляет около 1%. Я подозреваю, что где-то в ядре или в swapoff происходит обход списков (который использует ~ 90-100% ЦП). Конечно, если все работы выполняются последовательно и поиск дисков выполняется слишком медленно, это может значительно увеличить объем работы.
Томас Гайот-Сионнест
34

Я столкнулся с той же проблемой с моим ноутбуком, который имеет SSD, поэтому поиск времени не должен быть проблемой.

Я нашел альтернативное объяснение . Вот выдержка

Теперь, как это работает, swapoff просматривает каждую выгруженную страницу памяти в разделе swap и пытается найти все программы, которые его используют. Если он не может найти их сразу, он будет просматривать таблицы страниц каждой запущенной программы, чтобы найти их. В худшем случае он проверит все таблицы страниц для каждой выгруженной страницы в разделе. Это верно - одни и те же таблицы страниц проверяются снова и снова.

Так что это проблема ядра, а не что-нибудь еще.

Ник Крейг-Вуд
источник
1
Нет, это не проблема ядра ИМХО. Это как swapoffреализовано. Когда завершенный процесс завершается, это не занимает много времени.
Marki555
15
Это проблема с реализацией swapoff, которая находится в ядре - следовательно, проблема с ядром! Вы можете видеть, strace swapoffчто почти все, что он делает, это вызывает swapoffсистемный вызов.
Ник Крейг-Вуд
1
У меня есть сервер с 48 ГБ ОЗУ (32 ядра), было 6 ГБ, бесплатная ошибка подкачки была использована 0,7 ГБ. swappiness = 10, попытался сделать его 0, а также попытался swapoff, чтобы увидеть, что происходит. swapoff занимает целую вечность, вероятно, 30 минут, выпуская обмен очень медленно. У меня есть SSD практически без нагрузки, а процессор аналогичен, ожидаю, что процесс подкачки займет один процессор на 100%.
сорин
1
Это проблема реализации swapoff (в ядре). Несколько лет назад в kernel-dev были дискуссии о гораздо лучшем подходе, но они говорят, что это угловой случай и не хотят, чтобы его пытались изменить.
Marki555
7
На сервере с 1 ТБ ОЗУ (да, ТБ) и 2 ГБ подкачки (глупое требование SAP) для замены потребовалось 12 часов, чтобы освободить 5% из этих 2 ГБ (с 1 процессором на 100%).
Marki555
22

Да, swapoffмеханизм ужасно неэффективен. Обойти это легко: перебирайте процессы, вместо этого перебирайте переставленные страницы. Используйте этот скрипт Python (я не связан):

git clone https://github.com/wiedemannc/deswappify-auto

Обратите внимание, что режим работы демона предназначен только для настольных компьютеров / ноутбуков, которые часто находятся в спящем режиме. Я не запустил бы его как демон в серверной системе - просто запустите его на переднем плане, подождите, пока он сообщит, что он позаботился о некоторых процессах, затем остановите его и попробуйте:

swapoff /dev/x

Поскольку большинство страниц теперь присутствуют как в разделе подкачки, так и в памяти, swapoffони мало что могут сделать и теперь должны быть невероятно быстрыми (я видел сотни МБ / с).

Раздел истории впереди

Вышеупомянутый сценарий Python основан на остальной части этого ответа, который, в свою очередь, был моим улучшением этого более старого ответа, автором которого является jlong . Поскольку сценарий намного безопаснее, я рекомендую попробовать только оставшуюся часть моего ответа в качестве последней линии защиты :

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

Это работает , может быть , 2 секунды и не будет на самом деле сделать что - нибудь, просто список топа - 10 сегментов памяти ( на самом деле он печатает больше острот, да , я действительно люблю остроты, просто изучить команды, принять риск, скопировать и вставить в ваша оболочка, они на самом деле будут читать из свопа).

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

Основной однострочный текст безопасен (для меня), за исключением того, что он много читает / proc.

Подкоманды, подготовленные для вашего ручного обследования, небезопасны . Каждая команда повесит один процесс на время чтения сегмента памяти из раздела подкачки. Так что небезопасно с процессами, которые не терпят пауз. Скорость передачи, которую я видел, была порядка 1 гигабайта в минуту. (Вышеупомянутый скрипт Python устранил этот недостаток).

Еще одна опасность - слишком сильное давление памяти на систему, так что проверяйте, как обычно free -m

Что оно делает?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

Выход этого сценария Perl представляет собой серию gdbкоманд, dump memory (range)которые вызывают обмен страниц в памяти.

Выходные данные начинаются с размера, поэтому достаточно просто пройти его, | sort -Vr | headчтобы получить 10 самых больших сегментов по размеру (SSIZE). В -Vобозначает номер-версии, подходящей сортировки, но это работает для моих целей. Я не мог понять, как заставить работать числовую сортировку.

kubanczyk
источник
Вы бы использовали числовую сортировку здесь сsort -t = -k 2n
Стефан Chazelas
9
Кажется, нет необходимости использовать gdb для просмотра памяти процесса (по крайней мере, в последних версиях ядра). Можно просто открыть /proc/$pid/mem, искать и читать напрямую. Вот PoC, в значительной степени основанный на вашем фрагменте: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae Таким образом, процесс не останавливается, AFAIK не должно быть никаких опасностей, вызванных этим.
РГГ
10

Во время свопинга, если обнаружен используемый слот подкачки, ядро ​​сначала переставляет страницу. Функция unuse_process () затем пытается найти все записи таблицы страниц, которые соответствуют только что замененной странице, и производит необходимое обновление таблиц страниц. Поиск является исчерпывающим и очень трудоемким: он посещает каждый дескриптор памяти (всей системы) и просматривает записи в своей таблице страниц одну за другой.

Пожалуйста, обратитесь к странице 724 из "Понимание ядра Linux 3-я версия".

Лесли
источник