При поиске ошибок в сложных алгоритмах 1С, особенно в ситуациях, когда программа «зависает» или выбрасывает исключение, разработчики часто прибегают к инструменту «Замер производительности». Однако стандартный замер в конфигураторе предназначен в первую очередь для оптимизации: он группирует данные по количеству вызовов и суммарному времени, не предоставляя прямой хронологической последовательности выполнения строк кода. В этой статье мы разберем, как вычислить «последнюю точку» перед сбоем, используя стандартные и продвинутые инструменты платформы.
Рассмотрим типичную ситуацию: документ зависает при проведении, и нам нужно понять, на какой именно строке это происходит. Если включить замер, а затем принудительно прервать сеанс, мы получим таблицу, отсортированную по времени исполнения. Это не дает ответа на вопрос, какая строка была выполнена последней. Замер производительности в 1С не имеет встроенной функции сортировки по порядку выполнения (хронологии). Тем не менее, существует несколько методик, позволяющих обойти это ограничение.
Проанализируем самый простой способ работы с уже полученными данными замера. Несмотря на отсутствие хронологии в общем списке, мы можем использовать группировку. Если отсортировать результат замера по колонке Модуль, мы увидим все строки одного программного блока вместе. В пределах конкретной процедуры или функции строки кода, как правило, отображаются в порядке их написания. Просмотрев модули, которые потенциально могли исполняться последними, мы сможем увидеть, на какой строке обрывается замер.
Если замер не дает ясной картины, воспользуемся Стеком вызовов. Это один из самых недооцененных инструментов при поиске места зависания. Разберем алгоритм действий:
Если мы подозреваем, что происходит ошибка, стоит включить опцию «Остановка по ошибке» (Меню Отладка — Настройка отладки — Останавливаться по ошибке). В этом случае отладчик сам «выбросит» нас в ту строку кода, где возникло исключение, до того как оно будет обработано платформой или закроет сеанс.
Рассмотрим более детальный подход, если проблема воспроизводится только в многопользовательской среде или на сервере. Посмотрим на алгоритм, предложенный опытными разработчиками:
F10 (шаг через процедуру).F10 выполнение не переходит на следующую строку, а «замирает», значит, проблема внутри текущей процедуры.F11 (шаг в процедуру). Повторяем процесс рекурсивно до нахождения конкретной строки.Когда отладка невозможна (например, на «живой» базе, где нельзя ставить точки останова), на помощь приходит Технологический журнал. Это наиболее мощный инструмент для фиксации реального порядка выполнения событий на сервере. Для поиска зависания нам нужно настроить сбор событий CALL.
Пример настройки файла logcfg.xml для отслеживания длительных вызовов:
<config xmlns="http://v8.1c.ru/7.4/config/log">
<log location="C:\Logs\V8_Logs" history="2">
<event>
<eq property="Name" value="CALL"/>
<gt property="Duration" value="10000000"/> <!-- Фиксируем вызовы дольше 10 секунд -->
</event>
<property name="All"/>
</log>
</config>
Проанализируем лог: последняя запись CALL, для которой нет соответствующего завершающего события, и будет местом, где поток управления «застрял».
Выясним причину зависания, если она связана с параллельной работой пользователей. Часто программа не «висит» из-за бесконечного цикла, а ожидает освобождения ресурса. В этом случае замер производительности покажет, что время тратится на одной строке (например, ДокументОбъект.Записать()).
Если все вышеперечисленные методы недоступны, разберем метод «хлебных крошек». В критические участки кода (начало проведения, перед вызовом внешних систем) добавим запись в текстовый файл или в Журнал регистрации. Важно использовать методы, которые не кэшируют запись, чтобы данные сохранились даже при «убийстве» процесса.
Пример кода для трассировки в файл:
ТекстЛога = Новый ЗаписьТекста("C:\temp\trace.log", КодировкаТекста.UTF8, , Истина);
ТекстЛога.ЗаписатьСтроку(ТекущаяДатаСеанса() + ": Запуск процедуры ОбработкаПроведения");
ТекстЛога.Закрыть();
Проанализировав такой файл после зависания, мы увидим последнюю успешно пройденную отметку. Это позволит локализовать проблему с точностью до нескольких строк кода.
Подведем итог: хотя штатный замер производительности не умеет сортировать строки хронологически, комбинирование сортировки по модулям, использование стека вызовов и Технологического журнала позволяет вычислить проблемное место. В большинстве случаев «зависание» оказывается либо бесконечным циклом (выявляется стеком вызовов), либо ожиданием блокировки (выявляется в консоли кластера), либо конфликтом при обращении к внешнему оборудованию.