Почему количество выполнений в замере производительности превышает количество итераций цикла

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

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

Механика работы блока Попытка — Исключение

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

Разберем алгоритм фиксации:

  1. Профайлер фиксирует вход в строку и попытку её выполнения. Счетчик инкрементируется (+1).
  2. Если выполнение прерывается исключением (например, сетевой таймаут или ошибка сервера), платформа фиксирует факт возникновения ошибки именно на этой строке перед тем, как передать управление в блок Исключение. В этот момент счетчик инкрементируется повторно (+1).

Проанализируем конкретный пример из практики. Допустим, мы выполняем 10 попыток подключения к серверу. Из них 8 завершились ошибкой таймаута, а 1 — успехом (после чего мы прервали цикл). Формула расчета в замере будет выглядеть так: 8 (ошибок) * 2 + 1 (успех) = 17 выполнений. Рассмотрим, как это выглядит в коде:


Для Ш = 1 По 10 Цикл
    Попытка
        // Строка, которая в замере покажет "двойное" выполнение при ошибке
        Ответ = Соединение.ОтправитьДляОбработки(ЗапросPOST); 
        Прервать; // Если успешно - выходим
    Исключение
        // Обработка ошибки
        ЗаписьЖурналаРегистрации("Ошибка связи", УровеньЖурналаРегистрации.Ошибка);
    КонецПопытки;
КонецЦикла;

В данной ситуации, если сервер ответил не сразу, а после нескольких неудачных попыток, количество в колонке «Количество» будет всегда больше реального числа итераций цикла.

Особенности высокоуровневых методов HTTPСоединение

Рассмотрим вторую причину, связанную с методом ОтправитьДляОбработки или его аналогами (ВызватьHTTPМетод, Получить). Эти методы являются «высокоуровневыми» обертками над системными вызовами операционной системы. Выясним, почему это важно для замера производительности.

Внутренняя реализация платформы 1С может выполнять дополнительные действия при вызове одной строки встроенного языка:

Хотя для программиста это выглядит как один вызов ОтправитьДляОбработки, профайлер 1С, чувствительный к возвратам управления из внешних библиотек, может ошибочно фиксировать повторные «вхождения» в выполнение этой же строки кода.

Влияние версии платформы и отладчика

Проанализируем техническую сторону вопроса. В версиях платформы 8.3.15–8.3.18 наблюдались особенности работы профайлера при включенном режиме отладки. Если выполнение строки занимает значительное время (например, ожидание ответа от сервера в течение 30 секунд), замер производительности может вести себя нестабильно.

Это связано с тем, что механизм замера периодически опрашивает состояние потока выполнения. Если в момент ожидания сетевого пакета происходит прерывание контекста (например, вмешательство антивируса, проверяющего SSL-трафик, или системное прерывание ОС), то после возвращения управления в поток 1С счетчик может сработать повторно. Это явление часто называют «техническим дребезгом» счетчика профайлера.

Как проверить реальное количество выполнений?

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

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


СчетчикРеальныхВыполнений = 0;
Для Ш = 1 По 10 Цикл
    СчетчикРеальныхВыполнений = СчетчикРеальныхВыполнений + 1;
    Сообщить("Попытка № " + Ш); // Фиксируем итерацию в окне сообщений
    
    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(ЗапросPOST);
        Прервать;
    Исключение
        // Счетчик исключений тоже полезно вести отдельно
    КонецПопытки;
КонецЦикла;
Сообщить("Итого реальных вызовов: " + СчетчикРеальныхВыполнений);

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

Подведем итоги проанализированной ситуации

Столкнувшись с «лишними» выполнениями в замере производительности, не стоит искать ошибки в циклах или подозревать платформу в непроизвольном перезапуске кода. Основные выводы нашего разбора таковы:

  1. Исключения удваивают счетчик: Каждая ошибка в блоке Попытка добавляет лишнюю единицу в колонку «Количество».
  2. Сетевые задержки: Длительные ожидания ответа от сервера могут приводить к ложным срабатываниям счетчика из-за прерываний на уровне ОС.
  3. Замер — не истина в последней инстанции: Для точного подсчета бизнес-логики (сколько раз реально ушел запрос) следует использовать Журнал регистрации или вывод сообщений, а не профайлер.

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

← На главную