При разработке управляемых приложений на платформе 1С:Предприятие 8.3 мы, как разработчики, часто сталкиваемся с вопросом оптимизации производительности. Один из ключевых аспектов такой оптимизации — минимизация количества и объема серверных вызовов, особенно тех, которые могут быть неявными или скрытыми. Мы рассмотрим, как узнать, вызывает ли стандартный метод платформы обращение к серверу при вызове с клиента, и как эффективно управлять этим взаимодействием для повышения общей производительности системы.
Представим ситуацию: мы вызываем стандартный метод платформы, например, ТипЗнч(), из клиентского кода. Этот метод доступен как на клиенте, так и на сервере. Возникает закономерный вопрос: где на самом деле происходит исполнение этого метода, и не приводит ли его вызов к незаметному для нас обращению к серверу, что может существенно замедлить работу приложения, особенно при медленном соединении?
Для того чтобы достоверно выяснить, какие именно операции в нашем коде, включая вызовы стандартных методов платформы, приводят к обращениям на сервер, мы будем использовать мощный встроенный инструмент конфигуратора — Замер производительности.
Мы видим, что Замер производительности является наиболее точным и прямым способом отслеживания серверных вызовов. Этот метод дает нам конкретные данные по каждой строке кода, что неоценимо при оптимизации.
Мы выяснили, как отслеживать серверные вызовы, но давайте глубже разберемся, почему они возникают и как платформа управляет взаимодействием клиента и сервера. На самом деле, ситуация с серверными вызовами сложнее, чем простое разделение кода на клиентский и серверный.
Даже при работе исключительно на клиенте могут происходить обращения к серверу. Платформа 1С использует многоуровневое кэширование для ускорения работы и минимизации сетевого трафика. Это означает, что данные и результаты некоторых операций могут быть кэшированы как на клиентской, так и на серверной стороне. Например, первый вызов какого-либо значения или метода, требующего серверных данных, может привести к обращению на сервер, но последующие вызовы могут использовать кэшированные данные. Однако, если кэш "протух" или данные изменились на сервере, следующий вызов, даже того же метода, может инициировать новое обращение к серверу для получения актуальной информации.
Типовые сценарии неявных серверных вызовов:
ТипЗнч() требуется получить информацию об объекте, хранящемся в базе данных (например, для ссылки на объект), то платформа может выполнить серверный вызов. При этом, если тип значения может быть определен локально на клиенте (например, для переменной типа "Строка" или "Число"), то серверный вызов не потребуется.Понимание этих механизмов критически важно. Мы должны учитывать, что кэширование, хоть и ускоряет работу, может привести к ситуации, когда на клиенте видно устаревшее значение до перезапуска клиента или сброса кэша.
Основными задачами, которые мы ставим перед собой при оптимизации клиент-серверного взаимодействия, являются:
Регулярный контроль этих показателей с помощью замера производительности позволяет нам создавать более отзывчивые и эффективные приложения.
Теперь, когда мы понимаем механизмы и цели, давайте разберем конкретные стратегии для оптимизации взаимодействия между клиентом и сервером в 1С:Предприятии.
В управляемом приложении 1С мы можем явно указывать, где будет выполняться наш код — на сервере или на клиенте. Для этого используются директивы компиляции:
&НаКлиенте: Код будет выполняться только на клиентской стороне. Это минимизирует обращения к серверу, так как вся логика выполняется локально.&НаСервере: Код будет выполняться только на серверной стороне. При вызове такого кода с клиента весь контекст формы передается на сервер.&НаСервереБезКонтекста: Код будет выполняться на сервере, но при этом на сервер передаются только явно указанные параметры, а не весь контекст формы. Это значительно снижает объем передаваемых данных и является мощным инструментом для оптимизации.Давайте посмотрим на пример использования &НаСервереБезКонтекста:
// На клиенте
&НаКлиенте
Процедура ПриИзмененииРеквизита_НаКлиенте(Команда)
ЗначениеРеквизита = Объект.РеквизитФормы;
Результат = МодульСервераБезКонтекста.ВыполнитьСервернуюОперацию(ЗначениеРеквизита);
// ... дальнейшая логика на клиенте
КонецПроцедуры
// В общем серверном модуле с признаком "Вызов сервера" и "Сервер"
&НаСервереБезКонтекста
Функция ВыполнитьСервернуюОперацию(Параметр)
// Здесь мы работаем только с Параметром,
// контекст формы не передается
Возврат Параметр + 10;
КонецФункции
Мы должны стремиться максимально разделять логику, выполняя на клиенте то, что не требует серверных данных, и используя внеконтекстные вызовы на сервер для получения необходимых данных или выполнения серверных операций с минимальным объемом трафика.
Когда мы вызываем процедуру или функцию, помеченную директивой &НаСервере из формы, происходит так называемая "упаковка" всего контекста формы. Это включает в себя значения всех реквизитов формы, элементы управления и их свойства. Весь этот объем данных отправляется на сервер, затем обрабатывается, и после выполнения серверной логики контекст формы возвращается обратно на клиент. Это может быть очень ресурсозатратно, особенно для сложных форм с большим количеством реквизитов.
В противовес этому, использование директивы &НаСервереБезКонтекста является более эффективным подходом. В этом случае на сервер передаются только те данные, которые мы явно указали в качестве параметров процедуры или функции. Это существенно уменьшает объем передаваемых данных и сокращает время выполнения серверных вызовов. Мы должны по возможности избегать контекстных вызовов, если нам не нужен доступ ко всему контексту формы на сервере.
Платформа 1С использует многоуровневое кэширование для оптимизации работы. Мы можем влиять на некоторые аспекты кэширования для улучшения производительности.
C:\Users\User\AppData\Local\1C и C:\Users\User\AppData\Roaming\1C) или использовать команду запуска тонкого клиента /ClearCache для автоматического сброса кэша.ТипЗнч()Как мы уже упоминали, метод ТипЗнч() доступен как на клиенте, так и на сервере. Это означает, что его вызов на клиенте не всегда приводит к серверному вызову. Если тип значения может быть определен локально на клиенте (например, для простых типов данных или объектов, которые уже полностью загружены в клиентский кэш), то серверное обращение не потребуется. Однако, если для определения типа требуется получить дополнительную информацию о ссылке на объект в базе данных, которая не кэширована на клиенте, то может потребоваться серверное взаимодействие. Используя Замер производительности, мы сможем точно узнать, когда именно ТипЗнч() "ходит" на сервер.
Общие модули в 1С:Предприятии могут быть скомпилированы для выполнения как на клиенте, так и на сервере, или иметь оба признака. При вызове процедуры или функции из общего модуля платформа сначала ищет ее на клиенте. Если она не найдена, поиск продолжается на сервере. Чтобы обеспечить четкое разделение логики и избежать неопределенности, мы рекомендуем:
ОбщиеФункцииВызовСервера). Это сразу дает понять, что вызов этого модуля приведет к серверному обращению.В заключение, мы хотим поделиться общими рекомендациями, которые помогут нам поддерживать высокую производительность наших управляемых приложений:
&НаСервереБезКонтекста с передачей этого значения в качестве параметра.Применяя эти подходы, мы сможем значительно улучшить производительность наших решений на платформе 1С:Предприятие, делая их более быстрыми, отзывчивыми и удобными для пользователей.