Яким чином свопофф може бути таким повільним?


77

Якось мені трапилось поміняти 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

Читання частини розділу не може бути повільнішим, ніж його читання. Але читання приблизно однієї 10-ї частини займає приблизно в 100 разів більше.

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


1
Цікаво, чи відбувається таке ж явище, коли система завантажує замінені сторінки самостійно в оперативну пам’ять? Наприклад, якщо я систему призупинив на диску, а потім запустив, все було замінено і воно завантажується назад в оперативну пам'ять. Здається, і для мене це дуже повільно.
Петро Пудлак

Чи всі активізовані своп-пристрої активовані з однаковим пріоритетом?
Нілс

@Petr Pudlák: Підвіска до диска дещо інша, вона просто записує вміст ОЗУ у вільний простір в області підкачки, і це (і скасувати призупинення), ймовірно, набагато швидше. Я не можу спробувати, оскільки це не працює із зашифрованим свопом.
maaartinus

@Nils: Так, пріоритет такий же, як і диск та їх розділення.
maaartinus

Це робить його більш дивним. У цьому випадку заміна прокладається по всіх дисках - це повинно бути дуже швидким. Чи iostat -d 5виявлявся низький IO на дисках і під час swapoff?
Нілс

Відповіді:


53

Спочатку давайте розглянемо, що ви можете очікувати від вашого жорсткого диска. Ваш жорсткий диск може робити 200 Мб / с послідовно . Коли ви збираєтеся шукати час, це може бути набагато повільніше. Щоб вибрати довільний приклад, погляньте на характеристики одного з сучасних 3TB-дисків Seagate, ST3000DM001 :

  • Максимальна стійка швидкість передачі даних: 210 Мб / с

  • Шукайте середнє прочитане: <8,5 мс

  • Байтів на сектор: 4096

Якщо вам ніколи не потрібно шукати, і якщо ваш своп знаходиться біля краю диска, ви можете розраховувати на максимальну швидкість = 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
Відмінне пояснення. Слід зазначити, що можна обійти більшу частину фрагментації та швидко звільнити більшість свопів шляхом стримування ядрами
Брендон

Це не просто фрагментація / пошук часу. Моя заміна працює на SSD, і випадкові зчитування дуже швидкі, але команда swapoff працює набагато повільніше, ніж повинна, і моє завантаження SSD знаходиться приблизно на 1% утиліти. Я підозрюю, що десь в ядрі або в swapoff (який використовує ~ 90-100% процесора) десь перегляд списків. Звичайно, якщо вся робота виконується послідовно, а пошук диска теж повільний, це може значно доповнити.
Томас Гайо-Сіоннест

33

У мене виникли ті ж проблеми з моїм ноутбуком, який має SSD, тому прагнення до разів не повинно бути проблемою.

Я знайшов альтернативне пояснення . Ось уривок

Як він працює зараз, swapoff розглядає кожну сторінку, що перебуває у пам’яті, у розділі swap та намагається знайти всі програми, які її використовують. Якщо він не може їх знайти відразу, він перегляне таблиці сторінок кожної програми, що працює, щоб їх знайти. У гіршому випадку він перевірятиме всі таблиці сторінок для кожної заміненої сторінки в розділі. Це правильно – одні й ті ж таблиці сторінок перевіряються знову і знову.

Тож це швидше проблема ядра, а не все інше.


Ні, це не проблема ядра IMHO. Це як swapoffреалізується. Якщо процес заміни відбувається, це займе не так довго.
Marki555

15
Це проблема з реалізацією swapoff, який знаходиться в ядрі - отже, проблема з ядром! Ви можете побачити, якщо ви strace swapoffмайже все, що це робите , - це виклик swapoffсистемного виклику.
Нік Крейг-Вуд

1
У мене є сервер з 48 Гб оперативної пам’яті (32 ядра), у нього 6 ГБ вільної свопи помилок було використано 0,7 ГБ. swappiness = 10, спробував зробити 0, а також спробував змінити, щоб побачити, що відбувається. swapoff займає віки, можливо, 30 хвилин, вивільняючи своп надзвичайно повільно. У мене SSD майже не завантажується, і процесор схожий, очікуйте, що процес заміни займає один процесор 100%.
sorin

1
Це проблема того, як здійснюється swapoff (в ядрі). Кілька років тому в kernel-dev дискусії про набагато кращий підхід, але вони кажуть, що це кутовий випадок, і не хочуть, щоб зусилля його змінили.
Marki555

6
На сервері з 1 ТБ оперативної пам’яті (так, TB) і 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 сегментів пам'яті ( на насправді він друкує більше дотепів, так , я дійсно люблю гостроти, просто вивчити команди, прийняти ризик, скопіювати і вставити в ваша оболонка; вони фактично читатимуться із swap).

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

Основний однокласник безпечний (для мене), за винятком того, що він читає багато / проц.

Підкоманди, підготовлені для вашої ручної експертизи, не є безпечними . Кожна команда буде підвішувати один процес протягом тривалості зчитування сегмента пам'яті з підкачки. Тож це небезпечно для процесів, які не терплять жодних пауз. Швидкість передачі, яку я бачив, була в порядку 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позначає номер-версії, що підходить сортування, але це працює для моїх цілей. Я не міг зрозуміти, як змусити числову роботу сортувати.


Ви б тут використали числовий сортsort -t = -k 2n
Stéphane Chazelas

9
Здається, немає необхідності використовувати gdb, щоб заглянути в процесорну пам'ять (принаймні, на останні ядра). Можна просто відкривати /proc/$pid/mem, шукати та читати безпосередньо. Ось PoC багато в чому базується на вашому фрагменті: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae Цей спосіб не зупиняється, AFAIK не повинен бути небезпеками, викликаними цим.
WGH

10

Під час swapoff, якщо виявлено використовуваний слот для swap, ядро ​​спочатку поміняє сторінку. Потім функція unuse_process () намагається знайти всі записи таблиці сторінок, які відповідають щойно розміщеній сторінці та робить необхідне оновлення таблиць сторінок. Пошук є вичерпним та дуже трудомістким: він відвідує кожен дескриптор пам'яті (всієї системи) та вивчає записи його сторінок у таблиці по черзі.

Перегляньте сторінку 724 "Розуміння 3-ї версії ядра Linux".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.