Среди разработчиков 1С давно укоренилось мнение, что использование глобальных модулей — это «плохой тон» и признак непрофессионализма. Однако, если мы проанализируем механизмы работы платформы, становится понятно, что вопрос гораздо глубже, чем просто следование правилам хорошего тона. В этой статье мы подробно разберем, как именно 1С работает с программным кодом, когда происходит компиляция и почему мифы о «затирании кэша каждые 20 минут» могут вводить в заблуждение.
Давайте рассмотрим, что происходит «под капотом» системы при запуске сеанса. В 1С существует два основных подхода к подготовке программного кода к исполнению (компиляции в P-код):
Глобальный, платформа компилирует его сразу при старте системы. Это означает, что все методы такого модуля попадают в общую область видимости, и к ним можно обращаться напрямую, без указания имени модуля через точку.Проанализируем ситуацию: если мы поместим весь код в глобальные модули, время входа пользователя в систему значительно увеличится, так как серверу и клиенту придется скомпилировать огромный объем текста. Если же мы используем обычные модули, старт будет быстрым, но пользователь может почувствовать микро-задержку при первом открытии формы или нажатии кнопки, которая вызывает «тяжелый» нескомпилированный модуль.
Интересный нюанс возникает при использовании параметра запуска -debug. Разберем по шагам, как меняется поведение сервера:
В обычном режиме работы сервер старается экономить ресурсы. Но в режиме отладки серверу необходимо сопоставлять исполняемый P-код с исходным текстом для установки точек останова. Существует мнение, что при включенной отладке загрузка объектов может происходить по мере необходимости, чтобы облегчить работу конфигуратора. Однако на практике часто наблюдается обратное: для обеспечения стабильной отладки серверные модули могут прекомпилироваться более агрессивно при первом подключении отладчика или запуске первого пользователя. Это важно учитывать при замерах производительности — всегда проводите тесты на «боевом» сервере без флага отладки, так как цифры будут существенно отличаться.
В обсуждениях часто проскакивает цифра «20 минут», после которых кэш якобы затирается. Здесь важно мух отделить от котлет. Давайте выясним причину возникновения этой цифры:
Скомпилированный код модуля (P-код) живет в памяти процесса rphost (на сервере) или в памяти клиента в течение всего времени жизни сеанса. Он не удаляется «просто так» через 20 минут. Кэш сбрасывается только при завершении сеанса, перезапуске рабочего процесса или динамическом обновлении конфигурации.
Откуда же взялись 20 минут? Эта цифра относится к модулям с повторным использованием возвращаемых значений (кэширование результатов функций). Рассмотрим пример:
// В модуле с установленным свойством "Повторное использование"
Функция ПолучитьНастройкиПрограммы() Экспорт
// Этот код выполнится один раз, результат сохранится в кэше на 20 минут
Возврат Константы.НастройкиПрограммы.Получить();
КонецФункции
Именно для таких функций платформа по умолчанию хранит результат вычисления в течение 20 минут (если выбрано «На время сеанса»). К компиляции самого текста модуля это отношения не имеет.
Рассмотрим основные причины, по которым профессионалы избегают чрезмерного использования глобального контекста:
ПолучитьДанные() крайне велик. При использовании же ИмяМодуля.Метод() инкапсуляция защищает нас от этой проблемы.rphost растет лавинообразно, даже если пользователи просто открыли программу и ничего не делают.Если вы столкнулись с проблемой долгой «первой инициализации» модулей, проанализируем ситуацию и применим следующие шаги:
ПриНачалеРаботыСистемы) сделать «холостой» вызов самых важных модулей. Это заставит систему скомпилировать их заранее, но не «замусорит» глобальный контекст.Рассмотрим пример такого вызова:
Процедура ПриНачалеРаботыСистемы()
// "Прогреваем" важные модули фоновым или холостым вызовом
ОбщегоНазначения.ПустаяПроцедура();
ПроведениеСервер.ИнициализироватьКэш();
КонецПроцедуры
Подведем итог: Использование обычных общих модулей с обращением через точку — это стандарт проектирования, обеспечивающий чистоту кода и эффективное использование памяти. Глобальные модули допустимы только для тех функций, которые действительно требуются повсеместно и постоянно, но их количество должно быть строго ограничено.