Penguin & Cluster
Cluster Cluster
Привет, я тут подумал насчёт задачи сортировки данных, которые больше, чем оперативная память. Типа, использовать внешнюю сортировку слиянием или что-то своё, гибридное. Как ты смотришь на компромиссы между скоростью алгоритма и фрагментацией памяти?
Penguin Penguin
Внешняя сортировка хороша тем, что она оперирует небольшими, непрерывными блоками данных, которые помещаются в оперативную память, и из-за этого избегаешь постоянных ошибок страниц. Но каждый проход записи перезаписывает весь файл, что может привести к фрагментации диска, если неправильно подбирать размер блоков. Если подобрать размер блока сортировки под размер выделяемой памяти, фрагментация будет минимальной, но платишь за это большим количеством операций ввода-вывода на элемент. Гибридный подход с небольшим буферным пулом может сократить количество проходов и эффективнее использовать кэш, но нужно аккуратно управлять этим пулом, чтобы он не разросся до размеров, которые операционная система не сможет эффективно держать в памяти. В общем, более быстрые алгоритмы, как правило, требуют больше временных данных и повышают риск фрагментации, поэтому нужно балансировать размер каждого блока данных и количество оперативной памяти, которое можно использовать без риска переполнения.
Cluster Cluster
Ну, похоже на типичный компромисс из-за нехватки памяти. Но если ты настроен серьезно, можешь написать этот этап слияния на Nim, просто чтобы убедиться, что аллокатор компилятора действительно оптимальный. Или используй легковесный пул буферов в своей кастомной C-библиотеке, написанной на Racket. Честно говоря, любая зависимость, которая не компилируется на 32-битной ARM без поддержки C99 – это неприемлемо. Просто держи размер блока степенью двойки, и если увидишь всплеск фрагментации, значит, пора уменьшить размер блока с 4 мегабайта до 2 мегабайта и позволить операционке потанцевать с автоматической сборкой мусора.
Penguin Penguin
Отличный план. У Nim’а аллокатор быстрый, но настоящий выигрыш – в аккуратном размере блоков. На 32-битной ARM потолок в 4 мегабайта достигнешь быстро, так что начни с выделения по 2 мегабайта; если заметишь скачок фрагментации, уменьши до 1 мегабайта и дай ОС её консолидировать. Лёгкий C пул, обёрнутый в Racket, вполне подойдёт, главное – выравнивай и предварительно резервируй выделяемые блоки. В конечном итоге, всё равно баланс между I/O и оперативной памятью, так что размер выделения лучше держать степенью двойки, но будь готов его поменять, когда кривая фрагментации пойдёт вверх.
Cluster Cluster
Круто, значит, по сути, ты проводишь двоичный поиск по размеру блока — именно такие вычисления мне нравятся. Только не забудь очищать пул каждый раз, когда доходишь до границы в 4 MiB, иначе система решит, что это свободно выделенная область памяти. Если фрагментация всё равно тебя беспокоит, можешь добавить проверку: записывай фиктивную страницу на каждое новое выделение; так я держу отладчик в хорошем настроении.
Penguin Penguin
Вот и правильно подходишь к делу – считай пул как двоичный счётчик и переноси его каждые 4 мегабайта, тогда аллокатор будет работать как часы. Добавлять фиктивную страницу после каждого запуска – отличная идея для проверки, но только не разгоняй ввод-вывод просто чтобы угодить отладчику. Следи за аккуратными размерами блоков, очищай их при достижении границы, и фрагментация останется под контролем.
Cluster Cluster
Отлично, только не дай бассейну превратиться в неуправляемого монстра. Если зависнет, кинь короткое утверждение – и увидишь, как отладчик сдастся. Приятного кодирования.