Как немного ускорить работу клиентов Emby

Я уже достаточно давно стал использовать Emby в качестве своего основного медиасервера. С помощью него я слушаю музыку а также смотрю фильмы и сериалы из своей коллекции. Причем, делаю это не только дома, но и находясь в дороге, в отпуске или на отдыхе в выходные. Хотелось бы немного пояснить, в каком контексте я использовал словосочетание "достаточно давно". Как всегда, начну издалека, будет "много букв", поэтому особо нетерпеливые могут сразу перейти к описанию решения проблемы, озученной в заголовке.

Всем известна байка о том, что если компьютер с Windows долго не перезагружать (в смысле restart или reboot, кому как нравится), то он станет работать хуже и медленнее. Особенно эту байку любят распространять "апологеты"[1] Linux. Типа, огромное количество широко используемых сервисов (в том числе, и в самой Microsoft) работают на оборудовании под управлением Linux, uptime - просто сумашедший. "Попробуйте оставить свой компьютер с Windows поработать хотя бы недельку, - говорят такие специалисты - увидите, что с ним будет".

Почему я пишу "байка"? Неужели хочу обвинить достаточно большое количество людей в том, что они говорят неправду? На самом деле - нет, не хочу, у всех - своя правда, свой опыт и свои выводы. Тем не менее, я считаю, что сравнение серверов на *nix, на которых работают "широко используемые" сервисы, с домашними компами - несколько неправомерно.

Судите сами. Эти самые сервисы из себя представляют "вылизанное" ПО - они оптимизированы по памяти, быстродействию, оттестированы по максимуму, да и аппаратная платформа у них тоже не из подвальчика в подворотне.

А что же домашний компьютер? Был такой период моей профессиональной деятельности (середина 90-х), когда я, помимо собственноручно организованных компьютерных курсов, подрабатывал еще и тем, что носился по городу, в попытках разрешить проблемы пользователей домашних чудо-устройств. Чего я только не видел!

Отбросим в сторону неимоверное количество разнообразных вирусов - это обычная история, хотя я до сих пор не понимаю, откуда они умудрялись столько их нахватать в то "безинтернетовское" время. Гораздо интереснее более экзотические ситуации, встречавшиеся мне с завидным постоянством. Чего только стоили (в плане времени и нервов), например, два компьютера, собранных в одной и той же московской фирме (достаточно известной в то время), на базе одной и той же материнки, практически с одинаковыми комплектующими, отличающиеся только процессорами (вернее, их тактовой частотой), заполненные одинаковым софтом и, даже, стоящие по соседству, и показывающие чудеса в плане разницы производительности и стабильности - Pentium-100 работал, как часы, а Pentium-133 тормозил, зависал и перегружался. Потом оказалось, что, несмотря на спецификации, согласно которым и материнка и память должны были работать с Pentium-133, "в жизни" они этого не делали 😡.

На самом деле, являясь давнишним пользователем Windows, должен сказать, что, уже в конце 90-х, мой компьютер под управлением Windows NT 4 мог работать без перезагрузок и потерь потребительских свойств (имею в виду производительность), буквально, месяцами. Да и сейчас, мой ноутбук-трансформер (выпуска начала 2010-х) с Windows 10 Pro, c восемью гигабайтами памяти, исправно тащит на себе три виртуалки (VirtualBox), одна из которых отъедает почти четыре, а вторая - два гигабайта этой самой памяти (третья, правда, потребляет меньше гигабайта), и это при том, что мне не удалось полностью его очистить от предустановленного производителем софта.

И перегружается этот ноут только тогда, когда Windows решает, что без обновлений он больше работать не будет, хотя я этому сопротивляюсь, как могу. Кстати, да, вот эта вот особенность "десятки" - насильно установить обновление и перегрузиться - бесит больше всего, тут Linux, бесспорно, вне конкуренции.

Так, а к чему это я тут все развел? А, вот. Несмотря на то, что я, чуть выше, горячо защищал Windows, тем не менее, мнение о том, что софт, да и аппаратура тоже, при долгой эксплуатации могут проявлять признаки деградации, в принципе, имеет право на существование, да и подтверждений этому тоже можно найти достаточно.

Когда-то, на рубеже тысячелетий, у меня был такой опыт. В одной сотовой компании использовался наш софт для автоматизации работы склада. В качестве БД использовался Oracle, тогда еще версии 7.3, если не изменяет память. И я был, скажем так, довольно сильно (и приятно 😉) удивлен, когда, спустя год или полтора после начала эксплуатации, мы существенно улучшили быстродействие (пользователи стали жаловаться на медленную работу софта, хотя, поначалу, все было в порядке), просто экспортировав данные, "грохнув" старый экземпляр БД и импортировав эти же данные в новый экземпляр. Без изменения кода.

Вот. Теперь возвращаемя к Emby. Как я уже написал в первом абзаце, использую я его уже довольно давно. Довольно для того, чтобы начать замечать, что при открытии приходится долго ждать, когда же он покажет все то, что должен показать на главном экране приложения. Эти "тормоза" происходили на все типах клиентских приложений - приложении для Android, для Windows, из браузера. Да и от местоположения устройства замедление не зависило - происходило оно повсеместно, что при работе через интернет, что при нахождении в домашней сети.

Буквально в предыдущем посте я писал, что для того, чтобы ликвидировать "косячок", который сам же и сотворил (не без помощи софта, конечно же), пришлось мне немного поразбираться с внутренним миром Emby. И вот, после нескольких пересканирований медиатек, после разглядывания структур таблиц в БД SQLite и хранящихся в них данных, после осознания того факта, что, по сути, в программе применяется смешанный тип хранения (часть - в БД, часть - в файлах, а часть - в структуре каталогов), пришло мне на ум такое предположение - что, если "тормоза" эти связаны с тем, что содержимое файловой системы много раз сканировалось, структура этой самой системы менялась со временем, результаты каждый раз сохранялись в БД, старые данные (скорее всего) удалялись, в самой же БД все довольно, скажем так, денормализовано и, видимо, со временем накаплавается куча "хвостов" и дыр, от которых было бы неплохо избавиться. Короче говоря, основной причиной того, что главный экран (да и остальные тоже) стал долго отрисовываться, я полагал замедление скорости выполнения запросов к БД из-за сильной фрагментации данных в ней.

И надо сказать, что прямо руки у меня зачесались, как когда-то, в молодости (👶), сделать экспорт, грохнуть старую БД, а потом импортировать данные в новую. Но, к счастью (?), стал я не таким быстрым, более вдумчивым и занудным, к тому же, понимающим, что владею далеко не всеми знаниями. Потому, стал курить мануалы и форумы и, вскоре, нашел доказательства того, что я не одинок, есть еще определенное количество пользователей, страдающих из-за замедления работы. И тут я должен отметить, что в данном конкретном случае очень повезло и с разработчиками и с энтузиастами - именно благодаря крепкому сообществу я нашел нужный ответ и теперь могу поделиться им.

Во-первых, один из пользователей форума предложид workaround (обходное решение) для этой проблемы - замедление работы клиентов Emby с течением времени. Заключалось оно в том, что надо выполнить следующий набор действий:

  • остановить экземпляр Emby (автор решения использовал Emby, устанволенный на Linux, поэтому предлагал использовать команду systemctl stop emby-server)
  • выполнить для БД SQLite следующие команды:
sqlite3 /var/lib/emby-server/data/library.db "VACUUM"
sqlite3 /var/lib/emby-server/data/library.db "ANALYZE"
sqlite3 /var/lib/emby-server/data/library.db "REINDEX"
  • запустить сервер Emby (опять же, в оригинале это выглядело, как, systemctl start emby-sever)

Саму утилиту для работы с БД SQLite можно скачать на странице загрузки: для Windows надо найти и скачать файл sqlite-tools-win32-x86-xxxxxxx.zip, для Linux - sqlite-tools-linux-x86-xxxxxxx.zip, а для Mac - sqlite-tools-osx-x86-xxxxxxx.zip (xxxxxxx - номер версии SQLite, на момент написания этого текста он был равен 3300100, но, естественно, меняется со временем и поэтому прямых ссылок на файлы я не даю).

Во-вторых, разработчики не остались в долгу, и реализовали механизм, позволяющий выполнить эту операцию при помощи самого Emby: они добавили возможность определить в файле system.xml элемент VacuumDatabaseOnStartup - если установить для него значение true, то, при следующем запуске Emby, будет произведена обработка БД, аналогичная тому обходному решению, которое придумал участник форума.

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

#!/bin/bash

ls -lh /var/lib/emby/data/library.db > /root/emby-db-clean.txt
systemctl stop emby-server.service
xmlstarlet ed --update "/ServerConfiguration/VacuumDatabaseOnStartup" --value true /var/lib/emby/config/system.xml 
systemctl start emby-server.service
sleep 30
ls -lh /var/lib/emby/data/library.db >> /root/emby-db-clean.txt

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

  1. Останавливаем docker контейнер с сервером Emby:
docker-compose stop
  1. На всякий случай, пробуем обновить:
docker-compose pull
  1. Изменяем значения элемента в файле конфигурации (обратите внимание на путь к файлу system.xml - /full/path/to/mapped/from/container/system.xml; его надо заменить на путь, ведущий к нужному файлу у вас на компьютере):
sed -i 's:<VacuumDatabaseOnStartup>false</VacuumDatabaseOnStartup>:<VacuumDatabaseOnStartup>true</VacuumDatabaseOnStartup>:' /full/path/to/mapped/from/container/system.xml
  1. Запускаем контейнер:
docker-compose up -d

Такую последовательность уже не стыдно оформить в качестве скрипта и настроить его запуск через cron.

Предположим, запускать будем скрипт от имени того же пользователя, который используется для запуска самого сервера Emby - пусть это будет emby_user. Переключаемся на работу из под этого пользователя (su - emby_user) и в домашнем каталоге размещаем файл скрипта (назовем этот файл незамысловато, например, restart_cleanup.sh)[2]:

#!/bin/bash

docker-compose stop
docker-compose pull
sed -i 's:<VacuumDatabaseOnStartup>false</VacuumDatabaseOnStartup>:<VacuumDatabaseOnStartup>true</VacuumDatabaseOnStartup>:' /home/emby_user/vol/config/config/system.xml
docker-compose up -d

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

chmod +x /home/emby_user/restart_cleanup.sh

Теперь, при помощи команды crontab -e, создадим задание для cron (после запуска команды откроется окно редактора, в котором, после комментариев, надо просто добавить (скопировать) приведенные ниже строки):

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

45 4 1 * * /home/emby_user/restart_cleanup.sh

Сохраняем файл и все - первого числа каждого месяца, в 4:45 утра, будет запущен скрипт restart_cleanup.sh из каталога /home/emby_user.

На этом, пожалуй, все... А, нет, вот еще что... Если база у вас достаточно большая, то, возможно, придется подождать некоторое время, пока процедура приведения ее в порядок отработает полностью. Главное - не нервничать и не прерывать этот процесс, пока он сам не завершиться. В противном случае, могут возникнуть проблемы в виде испорченных БД SQLite. Вот небольшая выдержка из моего журнала работы Emby:

Как видите, у меня самая большая база обрабатывалась чуть больше 20 минут.

Вот теперь все.


  1. Определение "апологеты" взято в кавычки, так как настоящие апологеты такими глупостями не занимаются. ↩︎

  2. Приведенный скрипт можно развивать, например, добавить создание backup копий БД - мало ли, что пойдет не так, но ведь речь сейчас не об этом ↩︎