Почему серверные вызовы из клиентского приложения работают медленнее, чем через COM-соединение?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе «1С:Предприятие 8» программисты часто сталкиваются с тем, что идентичный код выполняется с разной скоростью в зависимости от контекста вызова. Одной из самых интересных и неочевидных ситуаций является существенная разница в производительности между обычным клиентским сеансом и внешним соединением (COM-Connector). Проанализируем этот феномен, опираясь на технические замеры и архитектурные особенности платформы.

Суть проблемы и результаты замеров

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

Вызов напрямую (из интерфейса клиента):

Вызов через соединение (COM-Connector):

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

Причина 1: Отсутствие графической подсистемы в COM

Разберем архитектурное различие окружений. Обычный клиент (тонкий или толстый) — это полноценное приложение с графическим интерфейсом. При каждом вызове сервера клиентское приложение не просто ждет ответа, оно продолжает обслуживать «Цикл обработки сообщений» (Message Loop) операционной системы Windows. Платформа должна реагировать на движения мыши, перерисовку окон, системные события.

В Внешнем соединении (COM) графическая подсистема не инициализируется вовсе. В этом контексте отсутствуют библиотеки отрисовки интерфейса, нет управления окнами и формами. Платформа работает в «облегченном» режиме, не тратя ресурсы процессора на поддержку визуального состояния, что дает преимущество «из коробки».

Причина 2: Синхронизация контекста и служебные данные

Проанализируем, что происходит «под капотом» при передаче управления с клиента на сервер. При обычном вызове из интерфейса 1С передает на сервер не только параметры процедуры, но и огромный объем служебной информации:

  1. Состояние навигации: сведения об активном окне и открытых формах.
  2. Глобальный контекст: данные, которые могут понадобиться серверу для синхронизации с клиентом.
  3. Очередь оповещений: проверка наличия новых сообщений, сгенерированных методом Оповестить() или изменениями в динамических списках.

В случае с COM-Connector этот балласт данных практически отсутствует, так как нет интерактивного пользователя, которому нужно обновлять экран или показывать сообщения немедленно.

Причина 3: Механизм прерывания пользователя (Ctrl+Break)

Важным фактором является встроенная проверка состояния клавиатуры. В клиентском приложении платформа обязана регулярно опрашивать состояние клавиш Ctrl+Break, чтобы пользователь мог прервать выполнение длительной операции. Даже если в вашем коде нет явного вызова функции ОбработкаПрерыванияПользователя(), система выполняет внутренние проверки при передаче управления.

Как показала практика, если поместить тот же самый код в модуль управляемого приложения в обработчик ПриНачалеРаботыСистемы(), скорость выполнения возрастает. Это происходит потому, что в этот момент главное окно интерфейса еще не инициализировано полностью, и механизмы мониторинга пользовательского ввода работают не в полную силу. Однако стоит коду выполниться через ПодключитьОбработчикОжидания() спустя 5 секунд после запуска, как скорость падает до стандартных «медленных» значений.

Влияние асинхронности на производительность

Интересным способом обхода «тормозов» интерфейса является использование асинхронных методов. Рассмотрим пример, где вызов серверного анализа выполняется после ответа на вопрос пользователю:


&НаКлиенте
Процедура ЗадатьВопрос(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Запустить тест?", РежимДиалогаВопрос.ОК);
КонецПроцедуры

&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, Параметры) Экспорт
    // В этот момент форма находится в состоянии ожидания и не обновляется активно
    РезультатАнализа = ТестированиеВнешнееСоединение.ВыполнитьАнализ();
    // Вывод результатов...
КонецПроцедуры

При таком подходе производительность может быть выше, так как в момент выполнения серверного метода через ОписаниеОповещения интерфейс формы «замирает» и не выполняет лишних циклов обновления GUI. Однако современные методы Асинх / Ждать в платформе 8.3.18+ показывают результаты, близкие к обычным вызовам, так как они глубже интегрированы в стандартный цикл событий клиента.


Асинх Процедура ЗапуститьТестАсинхронно()
    // Новый синтаксис асинхронности
    Результат = Ждать ВопросАсинх("Продолжить?", РежимДиалогаВопрос.ДаНет);
    Если Результат = КодВозвратаДиалога.Да Тогда
        ТестированиеВнешнееСоединение.ВыполнитьАнализ();
    КонецЕсли;
КонецПроцедуры

Выводы и рекомендации

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

Помните, что COM-Connector хоть и быстрее в ряде тестов, несет риски «зависших» сеансов на сервере, которые трудно диагностировать и закрывать. Поэтому для оптимизации интерфейсных вызовов всегда приоритетнее использовать переход к фоновому выполнению задач.

← На главную