.. ARU (c) 2018 - 2024, Pavel Priluckiy, Vasiliy Stelmachenok and contributors

   ARU is licensed under a
   Creative Commons Attribution-ShareAlike 4.0 International License.

   You should have received a copy of the license along with this
   work. If not, see <https://creativecommons.org/licenses/by-sa/4.0/>.

.. _extra-optimizations:

********************
Экстра оптимизации
********************

.. index:: cpu, governor, cpupower, scaling
.. _cpu_governor:

============================
Масштабирование частоты CPU
============================

В Linux существует специальные модули ядра, так называемые драйверы
масштабирования CPU. Они корректируют частоту вашего процессора в
режиме реального времени в зависимости от используемой политики
(``governor``) масштабирования частот процессора. Для x86 архитектуры
стандартным таким драйвером в ядре Linux принято считать
``acpi-cpufreq``, который, как понятно из названия, осуществляет
регулировку путем специальных вызовов APCI, которые устанавливают так
называемый P-state (Peformance state) уровень для вашего процессора.
Уровни P-State вашего процессора можно сравнить с коробкой передач у
автомобиля: он может лететь на всей скорости, ехать с обычной
автомобиля: он может лететь на всей скорости, ехать с обычной
скоростью, и стоять на месте в ожидании того, когда надо будет
сдвинуться с места. Собственно, по этой аналогии ``acpi-cpufreq`` и
переключается между 3-х стандартных P-State уровней в зависимости от
используемой политики масштабирования.

.. _governors:

---------------------------------
Политики масштабирования частоты
---------------------------------

Вернемся к политикам масштабирования частоты. Их можно сравнить с
планами электропитания в настройках Windows, только в отличии от них
политик масштабирования в Linux довольно много: ``performance``,
``powersave``, ``userspace``, ``ondemand``,
``conservative``, ``schedutil``.

Рассмотрим каждую из них подробнее:

``performance`` - как понятно из названия, данная политика
используется для достижения максимальной производительности, так как
она сильно снижает порог нагрузки, переходя через который процессор
начинает работать на полную мощность. Хорошо подходит для настольных
ПК, но не слишком желательно для использования на ноутбуках, где важна
автономность. Обратите внимание, что поведение данной политики зависит
от используемого драйвера масштабирования, об этом подробнее читайте
далее в разделе :ref:`pstate-drivers`.

``powersave`` - полная противоположность ``performance``, минимизирует
потребление энергии через занижение частот процессора до минимума.
Может быть очень полезно для ноутбуков при работе от батареи. Обратите
внимание, что поведение данной политики зависит от используемого
драйвера масштабирования, об этом подробнее читайте далее в разделе
:ref:`pstate-drivers`.

``ondemand`` - политика, которая регулирует частоту процессора на
основе общей нагрузки на процессор, то есть частота прямо
пропорциональна нагрузке: Чем выше нагрузка, тем больше частота, и
наоборот, чем ниже, тем ниже и частота. Конечно, скорость возрастания
частоты и нагрузки не всегда коррелируют между собой, ибо для принятия
решения о том, когда нужно повышать частоту до максимальных значений,
драйвер руководствуется значением параметра ``up_threshold`` (по
умолчанию 80%), которое устанавливает порог максимальной нагрузки в
процентах, которое должно достичь хотя бы одно из ядер вашего
процессора. К примеру, если у вас есть два ядра, и в текущий момент
времени драйвер масштабирования зафиксировал на одном ядре процессора
нагрузку в 70%, а на другом в 81%, то он станет повышать их частоты в
соответствии со значением ``up_threshold`` по умолчанию. Обратное
решение - понижение частоты CPU, драйвер принимает в соответствии со
значением другого параметра - ``down_threshold``, которое также
устанавливает порог ниже которого должно пройти хотя бы одно ядро
процессора, тогда частота будет понижена. Во всех остальных случаях
частота будет регулироваться как обычно, то есть пропорционально общей
нагрузке.

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

``conservative`` - должно быть вы замечали, как запуская игру или
"тяжёлое" приложение ваш компьютер или ноутбук начинает гудеть как
самолет, так как происходит резкое повышение частот процессора и
следовательно растет его температура. ``conservative`` очень похож на
политику ``ondemand``, но он делает процесс увеличения частоты CPU
более "гладким" и поступательным даже при значительном повышении
нагрузки. Это может быть очень полезным, когда вы не хотите чтобы ваш
ноутбук резко повышал свою температуру или уходил в так называемый
"турбобуст".

``schedutil`` - регулирует частоту процессора на основе метрик
планировщика CPU, например таких как количество активных процессов на
ядро процессора. Не слишком рекомендуется в силу того, что
использование данной политики часто приводит к резким скачкам частоты
без необходимости. Несмотря на это, данная политика используется по
умолчанию в стандартном ядре Arch Linux.

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

.. index:: amd-pstate, intel-pstate, cpufreq
.. _pstate-drivers:

------------------------------------------
Альтернативные драйверы масштабирования
------------------------------------------

Современные процессоры Intel и AMD могут самостоятельно осуществлять
масштабирование своей частоты на основе информации получаемой через
механизм *CPPC* (Collaborative Processor Performance Control), с
которым процессор получает от драйвера масштабирования "подсказку", о
том какой уровень производительности следует выдавать в данный момент.
Специально для работы с этим механизмом были созданы драйверы
amd-pstate (поддерживается процессорами Zen 2 и выше) и intel-pstate
(поддерживается Sandy Bridge и выше) для процессоров AMD и Intel
соответственно.

.. note:: Для процессоров Intel термин CPPC обычно не используется,
   так как их технология для автономного управления частотой
   процессора называется HWP (Hardware P-states), но суть остается той
   же, что и в случае с CPPC.

У драйверов P-state существует несколько режимов работы. Как для
intel-pstate, так и для amd-pstate есть ``active`` и ``passive``
режим, но для amd-pstate есть также ``guided`` режим.

В режиме ``active``, который используется по умолчанию во всех P-state
драйверах, управление частотой выполняется полностью автономно самим
процессором, но он получает от драйвера масштабирования "подсказку" -
так называемый уровень ``energy_performance_preference`` (далее EPP),
на основе которого процессор понимает с каким уклоном ему регулировать
собственную частоту. Таких уровней всего пять: ``power``,
``balance_power``, ``default``, ``balance_performance``,
``performance``. Как понятно из названия, эти уровни указывают
процессору предпочтение к тому, чтобы он работал на максимальную
мощность (при использовании уровней ``balance_performance`` и
``performance``) или наоборот экономил энергию и чаще принимал решение
о понижении своей частоты или уходе в состояние сна. По умолчанию
используется ``default``, что представляет собой баланс между
максимальной производительностью и энергосбережением.

Важно отметить, что классические политики для управления частоты,
которые мы описывали ранее, отходят на второй план, и более того, в
режиме ``active`` вы сможете выбрать всего две "фиктивные" политики
масштабирования, это ``powersave`` и ``performance``. Обе из них не
оказывают того влияния на частоту процессора, которое мы приписывали
им ранее, так как в режиме ``active`` драйвер не может самостоятельно
устанавливать частоту процессора и теперь это зависит только от
используемого значения EPP. Поэтому при выборе ``performance``
политики вы на самом деле просто измените текущий уровень EPP на
``performance``, значение которого P-state драйвер передаст процессору
через специальный регистр. Но при переключении политики на
``powersave`` уровень EPP не измениться и вы должны будете установить
его самостоятельно (об этом читайте далее).

При использовании режима ``passive`` P-State драйвер может напрямую
устанавливать желаемый уровень производительности, в связи с чем в нем
доступен полный набор политик масштабирования, о которых мы говорили
ранее. При этом установить уровень EPP становится невозможно, так как
процессор уже не управляет частотой полностью самостоятельно, а
ожидает переключения уровня P-State со стороны драйвера
масштабирования. Данный режим отличается от использования
классического драйвера ``acpi-cpufreq`` тем, что драйвер переключается
не между 3-мя уровнями P-State, которые определены стандартом ACPI, а
между сразу всеми доступными диапазонами частоты для вашего
процессора, что гораздо эффективнее.

Для драйвера ``amd-pstate`` существует также третий режим работы -
``guided``. Он работает аналогично режиму ``active``, позволяя
процессору самому управлять частотой, но при этом драйвер может
устанавливать процессору пороги минимальной и максимальной частоты,
что позволяет использовать классические политики масштабирования как в
случае с ``passive`` режимом.

Переключение между всеми тремя режимами может быть осуществлено как
при помощи соответствующих параметров ядра ``amd_pstate`` (например,
``amd_pstate=guided``) или ``intel_pstate`` в зависимости от
используемого драйвера масштабирования, так и прямо во время работы
системы при помощи файла ``status`` на псевдофайловой системе sysfs:

.. tab-set::

   .. tab-item:: AMD

     ::

       echo "passive" | sudo tee /sys/devices/system/cpu/amd_pstate/status

   .. tab-item:: Intel

     ::

       echo "passive" | sudo tee /sys/devices/system/cpu/intel_pstate/status

.. index:: cpupower, cpufreq
.. _cpufreq_tuning:

-------------------------------------
Настройка параметров масштабирования
-------------------------------------

Перейдем от теории к практике. Чтобы изменить текущую политику
масштабирования частоты можно воспользоваться множеством различных
способов, начиная от способа "руками" при помощи sysfs, заканчивая
специализированными утилитами как ``cpupower`` и
``power-profiles-daemon``, которые мы и будем использовать для
удобства. Для начала установим программу ``cpupower``::

   sudo pacman -S cpupower

С её помощью мы можем быстро увидеть информацию о текущей политике
масштабирования, используемом драйвере, а также текущую частоту::

  cpupower frequency-info

Установить желаемую политику масштабирования можно через команду
``frequency-set``. К примеру, установим политику ``performance``::

  sudo cpupower frequency-set -g performance

.. note:: Если команда ``cpupower frequency-info`` указывает на то,
   что используется P-State драйвер в автономном режиме, то не следует
   пытаться применять классические политики масштабирования при помощи
   ``cpupower``, вместо этого нужно указывать значение параметра
   ``energy_performance_preference`` (EPP) при помощи sysfs,
   например::

      echo "balance_performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference

   Узнать доступные значения параметра EPP можно через::

      cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences

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

Если вы хотите ограничить максимальную частоту процессора, то вы
можете использовать ключ ``-u``::

  # Ограничит максимальную частоту в 3 ГГц
  sudo cpupower frequency-set -u 3.0Ghz

Все проделанные изменения выше работают только до перезагрузки
системы, чтобы их сохранить нам понадобиться одноименный демон
``cpupower.service``::

  sudo systemctl enable --now cpupower

А также изменить конфигурацию ``/etc/default/cpupower``, которая
содержит все применяемые при запуске системы настройки. К примеру,
если вам нужно изменить политику масштабирования на постоянной основе,
то нужно указать значение параметра ``governor`` внутри
``/etc/default/cpupower``:

.. code-block:: shell
  :caption: ``sudo nano /etc/default/cpupower``

  governor='conservative'

.. note:: По умолчанию все строки в файле закоментированы. Чтобы
   раскоментировать нужные параметры уберите знак ``#`` в начале
   строки.

==========================================
Отключение спящего режима и гибернации
==========================================

У некоторых моделей материнских плат (в особенности китайских) может
некорректно или полностью не работать выход из состояния сна или
гибернации. В этом случае может быть полезным полностью отключить
переход в них при помощи ``polkit`` - графического менеджера по
передаче привелегий root пользователя, с помощью которого также можно
ограничивать доступ к определенным ресурсам. Установить его можно из
официальных репозиториев::

  sudo pacman -S polkit

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

.. code-block:: shell
  :caption: ``sudo nano /etc/polkit-1/rules.d/10-disable-suspend.rules``

  polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.suspend" ||
        action.id == "org.freedesktop.login1.suspend-multiple-sessions" ||
        action.id == "org.freedesktop.login1.hibernate" ||
        action.id == "org.freedesktop.login1.hibernate-multiple-sessions")
    {
        return polkit.Result.NO;
    }
  });


.. index:: swap, swapfile
.. _disabling-swap:

===========================
Отключение файла подкачки
===========================

Для лучшей игровой производительности следует использовать файловую систему
Btrfs и не задействовать файл подкачки (вместо него стоит использовать выше
упомянутый zram-generator, конечно при условии что у вас не слишком слабый процессор
и оперативной памяти больше чем 4 ГБ), а также без страха отключать фиксы
уязвимостей, которые сильно урезают производительность процессора (о них
написано в следующем разделе).

::

  sudo swapoff /dev/sdxy  # Вместо xy ваше название (Например sdb1).
  sudo swapoff -a         # Отключает все swap-разделы/файлы
  sudo rm -f /swapfile    # Удалить файл подкачки с диска
  sudo nano /etc/fstab    # Уберите самую нижнюю строчку полностью.

.. index:: makepkg, clang, native-compilation, flags
.. _force-clang-usage:

======================================================
Форсирование использования Clang при сборке пакетов
======================================================

В системах на базе ядра Linux различают две основных группы
компиляторов, это LLVM и GCC. И те, и другие хорошо справляются с
возложенными на них задачами, но LLVM имеет чуть большее преимущество
с точки зрения производительности при меньших потерях в качестве
конечного кода. Поэтому в целом применение компиляторов LLVM для
сборки различных пакетов при задании флага -O3 (максимальная
производительность) является совершенно оправданным, и может дать
реальный прирост при работе программ.

Компилятором для языков C/C++ в составе LLVM является Clang и Clang++
соответственно. Его использование при сборке пакетов мы и будем
форсировать через makepkg.conf

Для начала выполним их установку::

  sudo pacman -Syu llvm clang lld mold openmp

Теперь клонируем уже готовый конфигурационный файл ``/etc/makepkg.conf``
под новыми именем в домашнюю директорию ``~/.makepkg-clang.conf``::

  cp /etc/makepkg.conf ~/.makepkg-clang.conf

Это поможет нам в случае чего откатиться к использованию компиляторов
GCC если возникнут проблемы со сборкой пакетов через LLVM/Clang.

Теперь откроем выше скопированный файл и добавим туда после строки
``CHOST="x86_64-pc-linux-gnu"`` следующее::

  export CC=clang
  export CXX=clang++
  export LD=ld.lld
  export CC_LD=mold
  export CXX_LD=mold
  export AR=llvm-ar
  export NM=llvm-nm
  export STRIP=llvm-strip
  export OBJCOPY=llvm-objcopy
  export OBJDUMP=llvm-objdump
  export READELF=llvm-readelf
  export RANLIB=llvm-ranlib
  export HOSTCC=clang
  export HOSTCXX=clang++
  export HOSTAR=llvm-ar
  export HOSTLD=ld.lld
  export CXXFLAGS="${CFLAGS}"
  export LLVM=1
  export LLVM_IAS=1
  export CCLDFLAGS="$LDFLAGS"
  export CXXLDFLAGS="$LDFLAGS"

При использовании Clang из пакета `llvm-git` (установка описана ниже)
стоит включить использование LLVM OpenMP и компоновщика mold, а также
другие флаги при сборке пакетов: ::

  CFLAGS="-march=native -mtune=native -O3 -fexceptions -fopenmp \
          -falign-functions=32 -fno-math-errno -fno-trapping-math \
          -fcf-protection=none -mharden-sls=none -Wp,-D_FORTIFY_SOURCE=2 \
          -Wformat -Werror=format-security -fstack-clash-protection"
  CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
  export CFLAGS_KERNEL="$CFLAGS"
  export CXXFLAGS_KERNEL="$CXXFLAGS"
  export CFLAGS_MODULE="$CFLAGS"
  export CXXFLAGS_MODULE="$CXXFLAGS"
  export KBUILD_CFLAGS="$CFLAGS"
  export KCFLAGS="-O3"
  export KCPPFLAGS="$KCFLAGS"
  LDFLAGS="-Wl,-O3,--sort-common,--as-needed,-lgomp,-z,pack-relative-relocs,-z,relro,-z,now"
  LTOFLAGS="-flto=auto"
  RUSTFLAGS="-C opt-level=3 -C target-cpu=native -C link-arg=-z -C link-arg=pack-relative-relocs"
  #-- Make Flags: change this for DistCC/SMP systems
  MAKEFLAGS="-j$(nproc)"
  NINJAFLAGS="-j$(nproc)"
  OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge !debug lto)

.. warning:: Здесь мы используем некоторые флаги которые не
   рекомендуется использовать с точки зрения безопасности конечного
   кода для того чтобы увеличить производительность, как например
   ``-fcf-protection=none`` и ``-mharden-sls=none``, но если для вас
   безопасность такой же важный аспект как и производительность, то
   замените их на соответствующие флаги  на
   ``-fstack-clash-protection`` и ``-fcf-protection`` (флаг
   -mharden-sls можно просто опустить).

Отлично, теперь вы можете собрать нужные вам пакеты (программы) через
LLVM/Clang просто добавив к уже известной команде makepkg следующие
параметры::

  makepkg --config ~/.makepkg-clang.conf -sric --skippgpcheck --skipchecksums

.. attention:: Далеко не все пакеты так уж гладко собираются через
   Clang, в частности не пытайтесь собирать им Wine/DXVK, т.к. это
   официально не поддерживается и с 98% вероятностью приведет к ошибке
   сборки. Но в случае неудачи вы всегда можете использовать
   компиляторы GCC, которые у вас заданы в настройках makepkg.conf по
   умолчанию, т.е. просто уберите опцию ``--config
   ~/.makepkg-clang.conf`` из команды ``makepkg``.

Мы рекомендуем вам пересобрать наиболее важные пакеты. Например такие
как драйвера (то есть `mesa
<https://archlinux.org/packages/extra/x86_64/mesa/>`_, `lib32-mesa
<https://archlinux.org/packages/multilib/x86_64/lib32-mesa/>`_, если у
вас Intel/AMD), `Xorg сервер
<https://archlinux.org/packages/extra/x86_64/xorg-server/>`_, а также
связанные с ним компоненты, или `Wayland
<https://archlinux.org/packages/extra/x86_64/wayland/>`_, критически
важные пакеты вашего DE/WM, например: `gnome-shell
<https://aur.archlinux.org/packages/gnome-shell-performance>`_,
`plasma-desktop
<https://archlinux.org/packages/extra/x86_64/plasma-desktop/>`_. А
также композиторы `kwin
<https://archlinux.org/packages/extra/x86_64/kwin/>`_, `mutter
<https://aur.archlinux.org/packages/mutter-performance>`_, picom и
т.д. в зависимости от того, чем именно вы пользуетесь.

Больше подробностей по теме вы можете найти в данной статье:

https://habr.com/ru/company/ruvds/blog/561286/

.. index:: installation, x86_64_v2, x86_64_v3, alhp, repository, packages
.. _alhp_repository:

====================================
Установка оптимизированных пакетов
====================================

Нативная компиляция - это конечно хорошо, но не у каждого
человека есть время заниматься подобными вещами, да и всю систему
пересобирать с нативными флагами тоже никто не будет (иначе вам сюда:
https://gentoo.org). Возникает вопрос: как сделать все с наименьшим
количеством напряга?

Для начала сделаем небольшое отступление. У архитектуры *x86_64*
различают несколько поколений или "уровней". Это *x86_64*,
*x86_64_v2*, *x86_64_v3* и *x86_64_v4* (новейшие процессоры). Различия
между этими "поколениями" состоят в применяемом наборе инструкций и
возможностей процессора. Например, если вы собираете программу для
x86_64_v2, то вы автоматически задействуете инструкции SSE3, SSE4_1 и
т.д. При этом такая программа не будет работать на предыдущих
поколениях, то есть на процессорах которые не поддерживают набор
инструкций *x86_64_v2*. При этом к *x86_64_v2* и другим уровням
относятся различные процессоры, как AMD, так и Intel. При этом
логично, что чем выше поколение x86_64 поддерживает ваш процессор, тем
больше будет производительность за счет использования многих
оптимизаций и доп. инструкций. Подробнее об этих уровнях или же
поколениях можете прочитать `здесь (англ.)
<https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels>`__.

Смысл в том, что существует сторонний репозиторий Arch Linux - `ALHP
<https://git.harting.dev/ALHP/ALHP.GO>`__, который содержит **все
пакеты** из официальных репозиториев, но собранных для процессоров
x86_64_v2 или x86_64_v3. То есть это те же самые, уже готовые пакеты
из официальных репозиториев, но собранные с различными оптимизациями
для определенной группы процессоров (поколений x86_64).

.. danger:: Прежде чем мы подключим данный репозиторий, нужно
   **обязательно** понять к какому поколению относиться ваш процессор,
   иначе, если вы установите пакеты собранные для x86_64_v3, но *ваш
   процессор при этом не будет относиться к поколению x86_64_v3*, то
   *ваша система станет полностью не работоспособной*, хотя её и все
   ещё можно будет восстановить через LiveCD окружение при помощи
   pacstrap.

.. danger:: Оптимизированные пакеты для процессоров Intel поддерживают
   только полные процессоры серий Core 2 и i3/i5/i7. Многие процессоры
   Pentium/Celeron не имеют полного набора инструкций, необходимого
   для использования оптимизированных пакетов. Пользователям этих
   процессоров следует установить универсальные пакеты или пакеты
   оптимизированные ниже на один уровень (то есть если у вас
   поддерживается v3, то подключайте репозиторий с v2 и т.д.), даже
   если GCC возвращает значение, соответствующее полному набору флагов
   Core i3/i5/i7, например, Haswell.

Проверить поколение вашего процессора можно следующей командой::

  /lib/ld-linux-x86-64.so.2 --help | grep -B 3 -E "x86-64-v2"

После каждого поколения будет написано, поддерживается оно вашим
процессором или нет. Например::

  Subdirectories of glibc-hwcaps directories, in priority order:
  x86-64-v4
  x86-64-v3
  x86-64-v2 (supported, searched)

Если у вас поддерживается хотя бы x86_64_v2, то вы так же сможете
использовать данный репозиторий, ибо он предоставляет пакеты как для
x86_64_v2, так и для x86_64_v3. **Главное не перепутаете, какое именно у
вас поколение**.

Чтобы подключить репозиторий установим ключи для проверки подписей пакетов::

  # Ключи для пакетов
  git clone https://aur.archlinux.org/alhp-keyring.git
  cd alhp-keyring
  makepkg -sric --skippgpcheck

А также список зеркал::

  git clone https://aur.archlinux.org/alhp-mirrorlist.git
  cd alhp-mirrorlist
  makepkg -sric

После этого нужно отредактировать конфиг pacman добавив репозиторий
для нужной архитектуры (``sudo nano /etc/pacman.conf``).

Итак, **если ваш процессор поддерживает только x86_64_v2** (как
допустим у автора), то пишем следующее::

  [core-x86-64-v2]
  Include = /etc/pacman.d/alhp-mirrorlist

  [extra-x86-64-v2]
  Include = /etc/pacman.d/alhp-mirrorlist

  [multilib-x86-64-v2]
  Include = /etc/pacman.d/alhp-mirrorlist

  [core]
  Include = /etc/pacman.d/mirrorlist

  [extra]
  Include = /etc/pacman.d/mirrorlist

  [multilib]
  Include = /etc/pacman.d/mirrorlist

**Если же у вас процессор поддерживает x86_64_v3**, то пишем следующее::

  [core-x86-64-v3]
  Include = /etc/pacman.d/alhp-mirrorlist

  [extra-x86-64-v3]
  Include = /etc/pacman.d/alhp-mirrorlist

  [multilib-x86-64-v3]
  Include = /etc/pacman.d/alhp-mirrorlist

  [core]
  Include = /etc/pacman.d/mirrorlist

  [extra]
  Include = /etc/pacman.d/mirrorlist

  [multilib]
  Include = /etc/pacman.d/mirrorlist

После этого выполняем полное обновление системы::

  sudo pacman -Syyuu

Перезагружаемся и наслаждаемся результатом (если вы все сделали
правильно).


.. vim:set textwidth=70:
