Ядро для «памятливой» машины

Алексей Федорчук
3 сентября 2008 г

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

И первая неприятность — это настойчивый поиск ответа на вопрос, что же с этой 64-битностью, за которую, между прочим, уплочено, делать? В ходе этих поисков пользователи перебирают уже довольно многочисленные дистрибутивы, имеющие 64-битные версии. Однако далеко не все дистры таковыми располагают, это во-первых. А во-вторых, пользователь, нашедший-таки подходящую ему 64-битную систему, с удивлением обнаруживает, что ни малейшего прироста производительности за это он не получил (а на некоторых операциях, напротив, получил даже «урост»). Взамен обретая потенциальный источник проблем в виде отсутствия некоторых приложений и библиотек, собранных с поддержкой «повышенной разрядности», осложнений с драйверами устройств и прочих мелких, но досадных и не всегда решаемых неприятностей.

Собственно, единственное, что пользователь может реально получить от 64-битной системы — это поддержку больших объёмов памяти. Ведь модули суммарным объёмом в 4 Гбайт нынче обходятся во столько же, сколько пару лет назад пришлось бы выложить за один-единственный гигабайт. И потому машины с 4, а то и 8 Гбайт памяти нынче не выглядят чем-то экстравагантным.

Тем не менее, деньги за память, хотя и не астрономические, всё же плачены. И потому пользователю, обладающему четырьмя и тем более восемью её гигабайтами, очень обидно видеть, что его любимая 32-битная система находит из них лишь три гигабайта с небольшими копейками. И если, работая в Zenwalk’е (а он, как известно, существует только в 32-битном варианте) при 4 Гбайт памяти я ещё готов был мириться с потерей примерно шестисот мегабайт, но, волею случая получив в свое распоряжение 6 Гбайт, ощутил непреодолимый приступ жадности. Не настолько сильный, чтобы сменить дистрибутив, но достаточный, чтобы вспомнить о более простом способе — пересобрать ядро на предмет включения поддержки больших объемов памяти.

Как известно, 32-битные варианты операционных систем (в том числе и Linux), вне зависимости от разрядности процессора, на котором они работают, способны адресовать до 4 Гбайт виртуальной памяти — суммы физической RAM и объёма раздела подкачки; это теоретически, на практике 32-битные версии Linux и BSD-систем (да и других ОС, в том числе и самой всеми любимой) видят около 3,25 Гбайт.

Аппаратное решение этой задачи появилось еще во времена 32-разрядных процессоров — в виде предложенного Intel механизма PAE (Physical Address Extend). Это расширение адресного пространства памяти до 36 бит, что позволяет поднять верхний предел адресации памяти до 64 Гбайт. И механизм этот поддерживается ядром Linux ещё с тех времён, когда для большинства пользователей настольных персоналок даже 1 Гбайт памяти казался верхом роскоши. Остаётся только включить эту поддержку: и умолчальный конфиг из дерева исходников текущих версий ядра, и прекомпилированные ядра большинства современных дистрибутивов рассчитаны на использование не более 4 Гбайт памяти (с вышеуказанной поправкой).

Для включения поддержки памяти большого объема запускаем команду

$ make menuconfig

(предполагается, что все описанные в предыдущей заметке подготовительные действия, включая копирование конфига текущего ядра, выполнены) и в сгенерированном меню открываем пункт Processor type and features.

Раз уж мы занялись процессорными опциями, в развернувшемся вложенном меню для начала отыскиваем пункт Processor family (рис. 1). Большинство современных дистриубтивов (и их штатных прекомпилированных ядер) в своих 32-битных вариантах собираются с поддержкой процессоров i486 (как Zenwalk, который выступает у нас в качестве примера), i586 (например, Mandriva) или i686 (Archlinux, CRUX).


Рис. 1. Processor family (486) — умолчание ядра Zenwalk

Но мы-то располагаем процессором Intel Core 2 Duo, отделенном от умолчального i486 нашего ядра многими и многими поколениями. И к тому же, как мы помним, процессор 486 ни о каком PAE и слыхом не слыхивал, так что, если не включить поддержку процессора, начиная с PentiumPro и выше,  действия по регулированию памяти окажутся невозможными: соответствующих опций в меню мы просто не увидим.

Так что изменяем соответствующую опцию, включая поддержку процессоров нашего семейства Intel Core 2 Duo (рис. 2).


Рис. 2. Включение поддержки Core 2/newer Xeon

В результате этой операции опции конфига (после выхода из сценария настройки) изменятся таким образом: строка

CONFIG_M486=y

превратится в

# CONFIG_M486 is not set

а строка

# CONFIG_MCORE2 is not set

в

CONFIG_MCORE2=y

Теперь займёмся памятью. Выйдя из подпункта Processor family, «этажом выше» отыскиваем пункт High memory support, в котором по умолчанию стоит значение 4 Гбайт (рис. 3), и, открыв его, находим подпункт 64GB, каковой и выбираем кнопкой Select (рис. 4).


Рис. 3. High memory support (4GB) — умолчание ядра дистрибутива Zenwalk


Рис. 4. Включение поддержки памяти до 64 Гбайт

В файле конфигурации ядра это отражается так: строки

CONFIG_HIGHMEM4G
# CONFIG_HIGHMEM64G is not set

заменяются на

# CONFIG_HIGHMEM4G is not set
CONFIG_HIGHMEM64G=y

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

С памятью всё сразу становится ясно. Утилиты top и htop показывают (рис. 5 и 6, соответственно), что её объем вырос до реально наличествующих 6 Гбайт.


Рис. 5. Объем памяти: показания top


Рис. 6. Объем памяти: показания htop

Это конечно, радует — не будет мучительно больно за бесцельно потраченные деньги. А вот даёт ли это что-нибудь с точки зрения быстродействия? Особенно с учётом того, что ядро у нас теперь ещё и оптимизировано вроде бы точно под имеющийся процессор, что само по себе, согласно многочисленным легендам, бытующим среди уфологов, атлантологов, последователей Фоменки и пользователей Gentoo и LFS, обещает невиданный прирост производительности.

Каюсь — и автор этих строк приложил руку к созданию таких легенд. В оправдание чего могу сказать только, что это было во времена, когда процессоры были медленными, и каждый выигранный на оптимизации «попугай» радовал глаз, сердце, а иногда даже карман. Ныне же сравнение производительности чего бы то ни было с чем угодно, превратилось в спорт, и напоминает фотофиниш на стометровке.

Да, визуально (то есть сугубо субъективно) система выглядит несколько более быстрой (хотя задумчивостью она не отличалась и до этого). Но ведь это свойство человеческой натуры — иррационально верить в то, что сделанное им для себя с затратой сил и времени будет обязательно лучше того, что он получил вместе со всеми и даром. И потом — сколько раз мы сталкивались с тем, что «нас возвышающий обман» ощущений разбивается о «тьму низких истин» измерений? Так что поверим-ка алгеброй тестов гармонию восторгов и амбиций…

Самый простой способ определить эффективность влияния ядра на работу системы — измерить время компиляции ядра же, что я и проделал для исходников ядра версии 2.6.26.3 в умолчальной конфигурации, то есть после запуска сценария make menuconfig и выхода из него с сохранением изначальных опций, без всяких модификаций. Поскольку заодно я решил получить представление и об эффективности распараллеливания задач на двухпроцессорной системе, было выполнено две пары тестов.

Первая — сборка в системе с прекомпилированным ядром 2.6.26, умолчальном для Zenwalk 5.2 ветки snapshot на 31 августа, посредством команд

$ make all

и

$ make -j4 all

Вторая пара — сборка ядра теми же командами, но при загруженном ядре 2.6.26.3, собранном описанным выше способом, то есть с включением опций

CONFIG_MCORE2=y

и

CONFIG_HIGHMEM64G=y

Время сборки измерялось по показателю real из вывода команды time. То есть в каждой паре тестов сборка выполнялась сначала командой

$ time make all

а затем

$ time make -j4 all

После проведения каждой сборки каталог с деревом исходников удалялся, и для следующего теста распаковывался заново из архива.

Результаты измерений приведены в таблице

Таблица. Время сборки ядра, вывод значения real команды time, мин:сек

Ядро/команда make all make -j4 all
Умолчальное ядро 2.6.26 15:37 8:05
«Оптимизированное» ядро 2.6.26.3 15:22 7:56

Комментарии излишни: время сборки под умолчальным и «оптимизированным» ядром при прочих равных условиях отличается столь незначительно, что это можно уложить в пределы ошибки эксперимента. Почти двухкратное увеличение скорости сборки при задании опции -j, конечно, не может не радовать. Да вот только влияет эта опция на быстроту компиляции — и, ни на что более. А многие ли из нас регулярно занимаются пересборкой ядра и других программ?

У проведённых экспериментов был ещё один побочный результат, не имеющий практического значения, но служащий предостережением. Первоначально я выполнял сборку ядра из исходников тестируемой ныне версии 2.6.27 — учитывая достаточно высокий номер последнего релиз-кандидата, от неё можно было бы ожидать вполне стабильной работы.

«Мамэдка так думал… А как вишло?» Ядро с описанными выше опциями собралось и загрузилось нормально. Да и работа системы под ним, вроде бы, нареканий не вызывала. До тех пор, пока я не запустил браузер (Iceweasel версии 3.01) и не бросил взгляд на индикатор загрузки процессоров. Так вот, сам факт запуска этого браузера, без всякой полезной нагрузки, обеспечивал стопроцентную загрузку обоих ядер процессора — открытие и закрытие страниц, окон, вкладок на этом никак не отражалось, ни в меньшую сторону, ни, понятно, в большую. Причём закрытие браузера тут же скидывало загрузку процессора до нормального состояния, мало чем отличающегося обычно от нуля.

С чем это связано — с недоработкой ли ядра, или с сочетанием тестируемого ядра и конкретной сборки Iceweasel из snapshot-ветки дситрибутива, гадать я не стал. Но такое положение дел не счёл нормальным и без всяких тестов откатился на только что вышедший стабильный релиз ядра 2.6.26.3, извлекши из проделанной работы только один результат: следует быть осторожным с тестируемыми версиями ядра при практической работе. Тем более, что ядро 2.6.27 не оправдало моих надежд в отношении новоприобретённой web-камеры, о чём я надеюсь рассказать со временем.

Ну а практическим результатом всех описанных действий стал доступ к памяти выше отметки 3,25 Гбайт. Компенсирует это затраченные усилия или нет — судите сами.

Ядро для «памятливой» машины: 1 комментарий

  1. Небольшая опечатка:
    Время сборки измерялось по показателю real из вывода команды time. То есть в каждой паре тестов сборка выполнялась сначала командой
    $ time make -j4

Обсуждение закрыто.