LINUX.ORG.RU
ФорумAdmin

Ускорение загрузки с HDD за счет специальной дефрагментации

 


1

4

Теоретически можно не просто поместить все файлы нужные для загрузки ОС в начало диска, но и сложить их в такой последовательности, чтобы для загрузки было бы минимальное количество перемещений головок жесткого диска.

Вручную на неполном диске это сделать несложно. Переместить на свободный диск всю систему. Потом скопировать обратно последовательно /boot, /etc/, /bin/, /lib, /usr/bin, /usr/lib и дальше в порядке вероятности доступа при загрузке. Но на живой системе постоянно поддерживать такое будет затруднительно.

В общем может кто-то уже изобретал такого рода дефрагментатор, который бы мог список указанных файлов держать последовательно и поближе к началу диска?

Перемещено hobbit из general


Ответ на: комментарий от xmikex

чисто технически в UNIX наоборот пытались использовать это на благо - разбрасывая подальше разные файлы. ибо вот поместил он /sbin в начале диска, а потом прилетела обнову и всё пошло по женскому органу! на колу мочало, начинай сначала! неразумно!

mumpster ★★★★★
()
Ответ на: комментарий от firkax

Еще небольшой нюанс, с усложнением HDD не всегда возможно точно утверждать как «виртуальные» секторы отображаются в физические

Эти небольшие погрешности появляются только у битых дисков и всё равно почти не влияют.

Вам не про «битые диски» написали, а про то, что неизвестно на каком физическом секторе расположен ваш логический сектор. btw головы при старте харда перемещаются на середину диска, надеюсь догадываетесь почему?

anc ★★★★★
()

А теперь самое важное почему дефрагментатор, который я хочу не имеет особого смысла:

Systemd пускает сервисы параллельно, т.е. оно будет читать файлы вразнобой в любом случае. Гарантировать, что столько параллельных процессов всегда будет затребывать файлы в одном порядке практически невозможно.

Пока буду копать в сторону однонаправленного чтения в page cache при загрузке. Ну типа когда будет готова цель local-fs-pre.target запускать скрипт, который будет все паузить(если это вообще возможно в systemd) и делать одно большое чтение по порядку всех файлов, которые нужны жирным процессам.

Salol
() автор топика
Ответ на: комментарий от i-rinat

У меня получилось такое, что кеш блочного устройства отдельно от кеша ФС.

Берём файл, определяем на каких он блоках (filefrag), делам dd этих блоков и dd файла через файловую систему.

Если делать dd if=/dev/sdX по смещениям, где лежит файл, то первый раз идёт чтение со скоростью носителя (специально делал на НЖМД), а потом Гигабайты/с, то есть из кеша. И при повторных запусках dd if=/dev/sdX чтения с устойства нет (если смотреть через /proc/sys/vm/block_dump). И на это никак не влияет vmtouch -e по имени файла, которому данные блоки принадлежат. И пока я не понял, как убрать эти блоки из кеша блочного устройства.

А потом делаем dd if=/dir1/dir2/file, смотрим скорость. При первом запуске со скоростью носителя читаются с устройства именно те сектора, что показывает filefrag. При повторном запуске чтения с носителя уже нет. И здесь vmtouch -e работает.

Но даже в таком случае можно хранить отображение списка фрагментов в список файлов

Но тогда как-то нужно в ядро слать запросы на чтение параллельно, чтобы если два файла лежат на диске один за другим, то ядро объединило запросы и читало кучу секторов разом.

mky ★★★★★
()
Ответ на: комментарий от Salol

почему это?
стильно, модно, молодёжно!
я про их недостатки знаю (случайная запись и истирание и т.д.), но по скорости чтения он однозначно кроет HDD как бык овцу!
а флажок W как раз всё решает )))

грузится в несколько раз быстрее, это заметно сразу.

mumpster ★★★★★
()
Ответ на: комментарий от anc

неизвестно на каком физическом секторе расположен ваш логический сектор.

И при этом для НЖМД в ядре не отключают readahead. А вдруг в этой заранее читаемой области все сектора физически в разных местах? Сколько лишних движений головки, если данные не понадобятся...

на середину диска, надеюсь догадываетесь почему?

Почему? Чтобы дольше читать таблицу разделов и загрузчик?

И покажите НЖМД в нормальном состоянии, у которого скорость линеного чтения первого гигабайта ниже, чем скорость линейного чтения последнего. Обычно чуть ли не в 2 раза различие.

mky ★★★★★
()
Ответ на: комментарий от mky

Почему?

Потому что «направо-налево» быстрее головам двигаться, чем «снизу наверх».

И покажите НЖМД в нормальном состоянии, у которого скорость линеного чтения первого гигабайта ниже, чем скорость линейного чтения последнего. Обычно чуть ли не в 2 раза различие.

Линейное чтение в два раза? Сказки.

anc ★★★★★
()
Последнее исправление: anc (всего исправлений: 1)
Ответ на: комментарий от mky

Что-то да, по экспериментам выходит, что кеши разные. Я был прямо уверен, что кеш общий. Возможно, потому что я ещё пробовал директории так кешировать, чтением блочного устройства, и это неплохо работало. Но директории это не файлы, да.

как-то нужно в ядро слать запросы на чтение параллельно, чтобы если два файла лежат на диске один за другим, то ядро объединило запросы и читало кучу секторов разом.

Где-то пару лет назад экспериментировал с подобными трюками, чтобы ускорить копирование кучи файлов с HDD. И как в первой итерации сделал для каждого фрагмента открытие и закрытие файла, в котором этот фрагмент находится, так в этом виде и оставил. Даже не стал убирать лишние close+open, если несколько фрагментов подряд относятся к одному и тому же файлу. Хотя это лишние сисколы, на которые уходит время, HDD настолько медленные, что даже неэффективный подход всё равно нагружает HDD чуть ли не до предела линейной скорости. Зачем тогда париться?

i-rinat ★★★★★
()
Ответ на: комментарий от anc

Линейное чтение в два раза? Сказки.

Вот тесты для какого-то старого диска: https://www.hdtune.com/HDTune_Benchmark.gif

Вот тесты для не настолько старого: https://www.addictivetips.com/app/uploads/2021/03/gnome-disks-fs8-fs8.png

Как видишь, линейные скорости в начале и в конце действительно почти в два раза отличаются.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

И подобные «наклонные» графики — признак «честного» НЖМД накопителя. А всякие SMR показывают «чудеса» на таком графике, типа если сектор «пустой», отдают нули со скоростью интерфейса.

Вот пример SMR: https://superuser.com/questions/1782810/strange-hd-tune-benchmark-for-western... или так: https://www.techpowerup.com/forums/threads/odd-hd-tune-results-can-anyone-hel...

Из современных дисков я измерял TOSHIBA-MQ04ABF100, правда не помню, напрямую через SATA или через USB-SATA. Вобще получил в начале 128, а в конце 62 Мбайт/с, то есть даже чуть больше чем в 2 раза.

Ну ещё один старый тест, хотя 500 Гб может для кого ещё актуально https://www.anandtech.com/show/2268/5

mky ★★★★★
()
Ответ на: комментарий от i-rinat

Зачем тогда париться?

Дак не мне же :) Это ТС что-то задумал сделать, вдруг ему задач недостаточно.

Про разные кеши мне вобще не понятно, пытался что-то читать, но читать про организацию памяти в ядре страшо. Что кеши разные, занимают в два раза больше ОЗУ, не страшно. Мне просто вобще не понятно, зачем кеш блочного устройства, если при чтении файла идёт чтение с диска, а не из этого кеша.

Интерестно, если не dd с диска через read(), а mmap() блоков /dev/sdX, что-то поменяется?

mky ★★★★★
()
Ответ на: комментарий от mky

Подозреваю там нет никаких двух кешей, и нет кеша блочного устройства, а есть кеш «файла» /dev/sda и кеш файла, который лежит на этом /dev/sda. Первый используется только если юезрспейс читает напрямую с него.

firkax ★★★★★
()
Ответ на: комментарий от mky

Спасибо, только сейчас доперло, что fincore показывает только наличие в page cache, но не в block cache.

Но мне кажется, что vmtouch -e таки изгоняет из block cache тоже. Когда я делал vmtouch -e для повторных тестов, то скорость чтения файлов падала в 2 раза. Т.е. файлы вылетали из кэша на всех уровнях.

И насколько я помню на начальных этапах dd повторный был быстрым, т.е. читало из кэша. Но при этом сами файлы читались медленно. Как будто page cache ни сном ни духом про block cache. Еще у меня есть подозрение, что у меня это из-за dm-crypt, где маппер на маппере и непонятно какой слой кэшируется.

В общем пока page cache видится самым универсальным вариантом.

Salol
() автор топика
Ответ на: комментарий от mky

Интерестно, если не dd с диска через read(), а mmap() блоков /dev/sdX, что-то поменяется?

Нет, не меняется, всё то же самое.

Что интересно, так это если смапить, скажем, /dev/sda в память, то mincore() показывает, что прямо всё содержимое /dev/sda уже «in core».

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от Salol

Но мне кажется, что vmtouch -e таки изгоняет из block cache тоже.

Может это от версии ядра зависит, я всё делал на 4.19 и у меня vmtouch -e чистит только page cache. То есть в выводе vmstat (или /proc/meminfo) размер buff (Buffers) не меняется.

Но, если сделать echo 1 > /proc/sys/vm/drop_caches то размер и cache и buff (в выводе vmstat) падает. Хотя в документации написано, что эта команда чистит только pagecache.

Как будто page cache ни сном ни духом про block cache.

У меня аналогично без всякого dm-crypt и такое поведение мне вобще не понятно. Зачем вобще Buffers, если потом, чтобы попасть в Cached (page cache) идёт чтение с физического диска.

mky ★★★★★
()
Ответ на: комментарий от mumpster

С этого тема начиналась, что ТС против разбиения диска на несколько разделов.

достаточно для всего

Ну не для всего, но bcache на ssd 120 Гб сделать можно и дальше решать задачу, как при выключении системы занести в bcache «нужные» файлы, чтобы был быстрый старт.

mky ★★★★★
()
Ответ на: комментарий от mky

Тогда наверно (всё что ниже - предположения, в ядре я не смотрел ничего) в buffers попадают метаданные файловой системы например. Класть прочитанное одновременно и в buffers и в pagecache плохо - будут лишние затраты и памяти и проца на копирование, поэтому файлы скорее всего читаются прямо в pagecache. А поскольку штатно файловые сектора попасть в buffers не могут - он их там и не ищет. Чего я в этой схеме не понимаю так это зачем было эти два вида кешей разными сущностями делать.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)

При запуске тебе все начинают писать в логи и весь твой план пойдёт по бороде. А так, по идее можно сделать какой-нибудь образ, который будет целиком вычитываться, засовываться в ramfs, потом подмонтироваться в /usr /bin /lib /etc там, где нужна инфа для загрузки. Я помню так firefox ускорял.

crutch_master ★★★★★
()
Ответ на: комментарий от mky

решать задачу, как при выключении системы занести в bcache

забавный способ вырезать гланды через заднее место ;) у EMC для этого раньше блоки со свинцовыми батарейками были,
дохли периодически конечно же, а особенно тяжело было их в симметриксах в 4B менять было :-(

я же говорю - мой способ гораздо оптимальнее в определённых условиях. ещё и сам собой решается вопрос с внезапным умиранием SSD т.к. всегда есть текущая копия на более вменяемым в этих случаях HDD.

я щаз про SOHO и бытовой сегмент, оптанов дома не держим-с ))))

mumpster ★★★★★
()
Ответ на: комментарий от firkax

эти два вида кешей разными сущностями делать.

Тоже не смотрел исходники ядра, но, вроде, там всё завязано на размер блока. То есть у Page Cache (Cashed) это размер страницы (обычно 4 кбайт), а Buffers Cache (Buffers) — размер сектора диска.

Но это моё преположение на основании man proc, где написано:

Buffers Relatively temporary storage for raw disk blocks

исходники ядра смотреть лень, а что-то нагуглить не получается, термины синонимы, на запросы гугл даёт общие обсуждения, а не что-то детальное.

mky ★★★★★
()
Ответ на: комментарий от mky

Зачем вобще Buffers, … попасть в Cached (page cache)

они же для разного! RTFM!

цитирую:

«Linux always tries to use RAM to speed up disk operations by using available memory for buffers (file system metadata) and cache (pages with actual contents of files or block devices).»

Nuff said!

mumpster ★★★★★
()
Ответ на: комментарий от i-rinat

в целом подтверждаю, сейчас стало интересно, попробовал:

0:0:0:0] disk ATA SEAGATE ST35000N .AZK /dev/sda
[1:0:0:0] disk ATA WDC WD7501AALS-0 0K05 /dev/sdb
[10:0:0:0] disk ATA Samsung SSD 860 4B6Q /dev/sdh
[11:0:0:0] disk ATA TOSHIBA DT01ACA3 ABB0 /dev/sdi

/dev/sdh: CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=1953525168 /dev/sdg: CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=5860533168 /dev/sdb: CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=1465149168 /dev/sda: CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=976773168 /dev/sdi: CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=5860533168

dd count=1024 bs=1024k if=/dev/sdh of=/dev/null
1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 2,61154 s, 411 MB/s

dd count=1024 bs=1024k if=/dev/sdh skip=952000 of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 2,55491 s, 420 MB/s

dd count=1024 bs=1024k if=/dev/sdi of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 5,36657 s, 200 MB/s

dd count=1024 bs=1024k if=/dev/sdi skip=2856487 of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 11,0965 s, 96,8 MB/s

dd count=1024 bs=1024k if=/dev/sdg of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 5,21137 s, 206 MB/s

dd count=1024 bs=1024k if=/dev/sdg skip=2856487 of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 10,7873 s, 99,5 MB/s

dd count=1024 bs=1024k if=/dev/sdb of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 10,8367 s, 99,1 MB/s

dd count=1024 bs=1024k if=/dev/sdb skip=714000 of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 16,511 s, 65,0 MB/s

dd count=1024 bs=1024k if=/dev/sda of=/dev/null 1073741824 байт (1,1 GB, 1,0 GiB) скопирован, 13,2221 s, 81,2 MB/s

dd count=1024 bs=1024k if=/dev/sda skip=476000 of=/dev/null 985686016 байт (986 MB, 940 MiB) скопирован, 23,8027 s, 41,4 MB/s

mumpster ★★★★★
()
Ответ на: комментарий от mumpster

Какой это «speed up disk operations», если нужные блоки лежат в Buffers, но чтобы они попали в Cached идёт физическое чтение с диска?

Для какого «разного»? Там содержимое одинаковое, ядро исходно так построено, что не расчитывает, что кто-то кроме него будет что-то писать на диск. То, что прочитано с диска остаётся тем, что прочитано с диска. Нужные блоки прочитаны с диска, лежат в ОЗУ, и ядро знает какие это блоки, следующий запуск dd возмёт их из ОЗУ. Но следущее чтение из файла полезет на НЖМД, хотя из ОЗУ взять быстрее.

В Buffers идёт всё, что читает dd с файла-устройства. Какая это «file system metadata»? Берём dd, читаем 100 Мбайт блоков, содержащих файл, получаем прирост Buffers (в meminfo) на 100 Мбайт. Так что ваш RTFM, это никакой не M(anual), а обычная надпись на заборе, не объясняющая в каком виде данных хранятся в Buffers и в каких случаях ядро к ним обращается.

mky ★★★★★
()
Ответ на: комментарий от wandrien

Потому что кеш должен быть в драйвере ФС а не на уровне блоков. Ведь не все блоки одинаково полезно кешировать, и даже LRU тут не даст норм ответ.

firkax ★★★★★
()
Ответ на: комментарий от wandrien

с SSD-кэшем на 4 GB. Не особо он ему помогает,

Просто винда не додумалась, что во время выключениея нужно в этот кеш заносить файлы, нужные при загрузке, чтобы быстро включаться :) Тогда ВАУ-эффект обеспечен.

mky ★★★★★
()
Ответ на: комментарий от mky

Видимо моё объяснение таки правильное было. В buffers попадает только то, что не попадает в page cache, обычно это как раз метаданные фс. Ну а если ты читаешь напрямую с /dev то это особый случай, попадает он тоже в buffers но ядру пофиг и оно не пытается никак это переиспользовать.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Возможно. Но при этом получается, что какой-то разный формат хранения в Buffers для метаданных и для данных, что-ли? Или разные функции взываются из драйвера ФС — чтение блока данных и чтение блока метаданных? Я в том плане, что почему лежащие в Buffers метаданные используются, а просто блоки — нет. Там ведь, по идее, только номер raw блока и всё.

И не понятно, зачем тогда помещать в Buffers простые блоки, которые, скорее всего, не будут использованы, ведь это какие-то операции с памятью, лишнее действия. Понятно, что «копейки», но всё ядро содержит кучу всяких оптимизаций, чтобы как можно меньше лишних действий. Надо ещё посмотреть, может ли рост Buffers от dd if=/dev/sdX вытеснять файловый кеш (Cached).

mky ★★★★★
()
Ответ на: комментарий от mky

Но при этом получается, что какой-то разный формат хранения в Buffers для метаданных и для данных, что-ли?

Почему разный? Кто-то читает устройство (драйвер фс или юзер) - закешируем его в buffers.

чтение блока данных и чтение блока метаданных

Подозреваю что «чтения данных» как такового в ядре вообще нет. Есть только «подгрузить недостающую страницу файла в его маппинг в памяти», аналогично свапу, а потом из неё уже копируется что надо при read(). Если сделать mmap() то этот маппинг будет в явном виде показан приложению. Самому ядру содержимое файлов не нужно.

И не понятно, зачем тогда помещать в Buffers простые блоки, которые, скорее всего, не будут использованы, ведь это какие-то операции с памятью, лишнее действия

Не знаю. Возможно решили не нарушать семантику наличия/отсутствия флага O_DIRECT в open(). И почему не будут использованы? Юзер зачем-то читает /dev/sda, вдруг ещё раз захочет?

firkax ★★★★★
()
Ответ на: комментарий от firkax

Юзер зачем-то читает /dev/sda, вдруг ещё раз захочет?

У меня получилось, что поведение ещё сложнее, чем описано мною ранее. dd if=/dev/sdaX заполняет Buffers, только если /dev/sdaX смонтировано. Если не смонтировано, то ни Buffers, ни Cached не меняется.

Получается, что если пользователь такой извращенец, что читает /dev/sdaX в обход драйвера ФС, то ядро будет забивать Buffers и при этом, когда память будет заканичаваться, освобожать Cached. Чтобы страдал без файлового кеша, ибо нефиг работать в обход драйвера ФС :) Конечно, потом, при чтении файлов, Buffers уходит, а Cached растёт.

А так, «ещё раз захочет», как-то сомнительно, обычно ведь dd на весь раздел, который больше объёма свободного ОЗУ, последние блоки, читаемые dd, вытяснят первые и новое чтение опять начнётся с носителя, а не из Buffers.

mky ★★★★★
()
Ответ на: комментарий от firkax

Подозреваю что «чтения данных» как такового в ядре вообще нет.

Не совсем корректно выразился, я размышлял, что, наверное, в ядре тоже есть какой-то аналог O_DIRECT и драйвер ФС читает данные файлов напрямую с носителя, а метаданные через Buffers.

Ядро ведь различает и как-то отдельно кеширует данные и метаданные, потому что man proc:

To free pagecache, use: echo 1 > /proc/sys/vm/drop_caches

To free dentries and inodes, use: echo 2 > /proc/sys/vm/drop_caches

И при этом у меня echo 1 уменьшает не только Cached (pagecache), но и Buffers, но не до нуля, а если после этого сделать echo 2, то Buffers наоборот станет больше, а Cached немного меньше. И это на простаивающей машинке, где iostat стабильно нули показывает.

По идее, раз сброс метаданных не приводит к снижению Buffers, значит они там не хранятся.

mky ★★★★★
()
Ответ на: комментарий от mumpster

Да, это физика, и так примерно ЕМНИП, со 120-250 Мбайт. Угловая скорость вращения постоянна, а линейную плотность бит стремятся держать на максиальном уровне. Получается ZBR (zone bit recording).

На нулевой физической дорожке секторов раза в два больше, чем на последней — примерное соотношение наружного диаметра магнитного диска и диаметра шпинделя, к которому он крепится. Возможно, что на 5,25″ НЖМД с ZBR соотношение скоростей было ещё больше.

mky ★★★★★
()
Ответ на: комментарий от mky

drop_caches

Эта рукоятка — тот ещё обман. Она сбрасывает некоторые кеши, но не все. Сбросить почти всё можно, позвав shrink_all_memory(-1) много раз. Одного раза недостаточно, нужно звать несколько раз, потому что каждый следующий вызов освобождает агрессивнее. Думаю, 12-13 раз достаточно.

Вот тут есть готовый модуль: https://github.com/i-rinat/utility-kernel-modules/blob/master/shrink-memory/shrink-memory.c. Давно не проверял, но есть шанс, что он всё ещё собирается и работает.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Да у меня не то чтобы задача сбросить кеши, мне просто интерестно смотреть на цифры. В ядро лезть не хочется, нет столько свободного времени чтобы эту безду (подсистему памяти) изучить. А так, что-то подёргать иногда руки чешутся :)

Вобще не понятно, этот drop_caches на простаивающем компе сбрасывает Buffers до 800-900 кбайт, но буквально за несколько секунд там уже 2-3 Мегабайта и прекращение роста. Хотя в таких объёмах с диском в этот момент никто не работает. Да и вобще iostat нули показывает. Что туда ядро засовывает? Slab ведь отдельно считается?

mky ★★★★★
()
Ответ на: комментарий от mky

По идее, раз сброс метаданных не приводит к снижению Buffers, значит они там не хранятся.

Метаданные - во всяких struct {} в памяти ядра. А в buffers - копии секторов, которые читались с диска чтобы получить эти метаданные. Возможно, после сброса инод он сразу начинает читать их заново, побочно растя buffers.

firkax ★★★★★
()