Я уже некоторое время смотрю на это, и все не совпадает с моими ожиданиями, но я не знаю, потому что что-то не так, или мои ожидания неверны.
Итак, у меня есть система с более чем 100 ГБ ОЗУ, и я установил свой dirty_background_bytes
на 9663676416 (9 ГБ) и dirty_bytes
в 2 раза больше (19327352832 или 18 ГБ)
На мой взгляд, это должно позволить мне записать до 9 ГБ в файл, но на самом деле он просто находится в памяти и не должен попадать на диск. Мой dirty_expire_centisecs
по умолчанию 3000
(30 секунд).
Итак, когда я бегу:
# dd if=/dev/zero of=/data/disk_test bs=1M count=2000
и побежал:
# while sleep 5; do egrep 'Dirty|Writeback' /proc/meminfo | awk '{print $2;}' | xargs; done
(Печать грязных байтов в килобайтах, обратная запись в килобайтах и WritebackTmp в килобайтах на моментальных снимках 5 секунд)
Я ожидал увидеть, как он выгружает 2 ГБ в кеш страницы, сидит там 30 секунд, а затем начинает записывать данные на диск (поскольку он никогда не превышал фоновое соотношение 9 ГБ)
Вместо этого я увидел:
3716 0 0
4948 0 0
3536 0 0
1801912 18492 0
558664 31860 0
7244 0 0
8404 0 0
Где, как только кеш страницы перескочил, он уже записывал данные, пока мы не вернулись туда, где начали.
На самом деле я работаю над тем, чтобы понять, является ли узкое место моего процесса дисковым вводом-выводом или каким-либо другим фактором, но в середине я запутался в таком поведении. Я полагаю, пока процесс все еще работает в буферной зоне, производительность записи на диск не должна иметь значения, поскольку она должна просто выгружаться в память.
Итак, я неправильно понимаю, как эти функции должны работать, или происходит что-то странное?
Это может быть побочным эффектом вашего dd
отключение команды и создание нового disk_test на каждой итерации.
Попробуйте сначала создать целевой файл с одним dd if=/dev/zero of=/data/disk_test bs=1M count=2000
команду, затем запустите цикл с помощью dd if=/dev/zero of=/data/disk_test bs=1M count=2000 conv=notrunc,nocreat
команда.
Пояснение: notrunc
имеет значение, потому что в прошлом была добавлена некоторая эвристика, чтобы предотвратить приложения, выполняющие замену через переименование и замену через усечение и сбой сразу после этого, чтобы повредить свои данные. Эта эвристика в основном принудительно сбрасывает данные, принадлежащие открытым-> записанным-> усеченным файлам.
Из смонтировать страницу руководства:
auto_da_alloc | noauto_da_alloc
Многие неработающие приложения не используют fsync (), когда noauto_da_alloc заменяет существующие файлы с помощью таких шаблонов, как
fd = open ("foo.new") / write (fd, ..) / close (fd) / rename ("foo.new", "foo")
или еще хуже
fd = open ("foo", O_TRUNC) / write (fd, ..) / close (fd).
Если auto_da_alloc включен, ext4 обнаружит шаблоны replace-via-rename и replace-via-truncate и принудительно распределяет любые отложенные блоки распределения таким образом, чтобы при следующей фиксации журнала в режиме data = order по умолчанию блоки данных новый файл будет записан на диск перед выполнением операции rename (). Это обеспечивает примерно тот же уровень гарантий, что и ext3, и позволяет избежать проблемы «нулевой длины», которая может возникнуть при сбое системы до того, как блоки отложенного распределения будут перенесены на диск.
Дайте также добычу в XFS FAQ