Граф вызовов модуля 1С: как найти точки нагрузки и мёртвые процедуры

05.10.26

Разработка - Рефакторинг и качество кода

Для 1С-разработчика: скрипт на Python 3, который по тексту файла `.bsl` строит карту вызовов внутри одного модуля, порядок выгрузки модулей в файлы, разбор прогона на учебном модуле из 17 процедур, чтение графа в Graphviz и Mermaid. Платформа для разбора не нужна, замеров производительности в статье нет.

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Скрипт графа вызовов модуля и пример
.zip 7,86Kb
0 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Вы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.
🚀 DevOps, CI/CD & Архитектура
🎯 О чём это - в трёх строках
🗸Скрипт строит карту вызовов модуля по тексту файла.
🗸Скрипт call_graph.py на Python 3, учебный модуль на 17 процедур, готовый граф в формате Graphviz.
🗸Карта показывает, с какой процедуры начинать чтение модуля, и отделяет мёртвые процедуры от точек входа.
🧠 Суть статьи

Для 1С-разработчика: как по тексту файла модуля построить карту вызовов, найти процедуры с наибольшим числом обращений, самую длинную цепочку вызовов и процедуры без вызовов. Скрипт на Python 3 разбирает выгрузку конфигурации в файлы, прогон на учебном модуле показан целиком.

Ключевые идеи
  • Разбор текста - скрипт читает файл `.bsl`, платформа для этого не нужна
  • Два прохода - объявления собираются до поиска вызовов, иначе вызов процедуры, объявленной ниже по тексту, считается внешним обращением
  • Четыре чтения графа - узлы без входящих связей, горячие узлы, длинные цепочки, порядок рефакторинга
  • Слепые зоны разбора - вызовы через строку, связи между модулями, обработчики по началу имени
  • Прогон с числами - 17 объявлений, 19 связей внутри модуля, пять вызовов проверки заполнения, цепочка из пяти переходов
Главная мысль

Текстовый разбор модуля даёт карту вызовов без платформы: видно, какие процедуры вызываются чаще всех, где цепочка тянется на пять переходов и какие процедуры не вызывает никто.

Для кого: 1С-разработчики, которым достался модуль объекта или общего модуля на сотни строк и нужно понять его устройство до первой правки.

Модуль объекта, который годами правили всей командой, читается тяжело по простой причине: у него нет карты. Строки есть, а структуры не видно. Вызовы разбросаны по сотням строк, одна и та же проверка дёргается из пяти мест, часть процедур не вызывается вовсе, и выясняется это только последовательным чтением сверху вниз.

Карту можно собрать из самого текста модуля. Достаточно найти все вызовы процедур и функций этого же модуля, посчитать входящие связи и посмотреть на результат: кто вызывается чаще всех, где самая длинная цепочка, какие процедуры висят без вызовов.

📦 Где взять текст модулей

Разбору нужен файл с текстом модуля; открытая форма конфигуратора для этого не годится. Текст модуля лежит в выгрузке конфигурации в файлы:

  • в конфигураторе: «Конфигурация - Выгрузить конфигурацию в файлы», каталог выбирается в диалоге;
  • из командной строки тем же действием: DESIGNER /DumpConfigToFiles <каталог выгрузки>;
  • из 1C:EDT: экспорт проекта или выгрузка в файлы для сравнения с базой.

В выгрузке каждому модулю соответствует отдельный текстовый файл с расширением .bsl, и имя файла говорит о роли модуля: модуль управляемой формы - Module.bsl, модуль объекта - ObjectModule.bsl, модуль команды - CommandModule.bsl, модуль менеджера - ManagerModule.bsl. Модуль объекта лежит внутри каталога своего объекта, модуль общего модуля - внутри каталога общего модуля. Кодировка файлов - UTF-8.

Скрипт умеет обойти всю выгрузку целиком: если вместо файла передать ему каталог, он найдёт все .bsl внутри рекурсивно. Для первого раза удобнее один модуль: отчёт по объекту на несколько тысяч строк сам превращается в свалку, и читать его приходится с фильтром.

🧱 Как устроен разбор

Скрипт call_graph.py из вложения делает четыре шага.

  1. Убирает из текста то, что мешает искать скобки. Строковые литералы и комментарии вырезаются, но переводы строк сохраняются, поэтому номера строк остаются на месте. Скобка внутри текста запроса или в комментарии не создаёт ложную связь.
  2. Собирает объявления. Строка Процедура Имя(...) или Функция Имя(...) даёт имя и признак Экспорт, если он есть в объявлении.
  3. Ищет вызовы. Вызовом считается имя, после которого идёт открывающая скобка. Служебные слова языка отбрасываются, обращения через точку тоже: Запрос.Выполнить() и Товары.Индекс() адресуют метод объекта и связи между процедурами модуля не создают.
  4. Достраивает связи. Связь появляется только между двумя процедурами одного модуля. Всё остальное - обращения к платформе и другим модулям - идёт в отдельный счётчик.

Ядро разбора - четыре строки: два шаблона регулярных выражений и два списка слов. Объявление ловится шаблоном ^\s*(?:Процедура|Функция)\s+([A-Za-zА-Яа-яЁё_]\w*)\s*\(([^)]*), вызов - шаблоном (?<![.\w])([A-Za-zА-Яа-яЁё_]\w*)\s*\(. Запрет на точку и букву перед именем вызова отсекает обращения к методам объектов: Запрос.Выполнить() в список не попадает. Служебные слова языка - если, иначеесли, пока, для, возврат, новый, не, и, или, ждать - тоже отбрасываются, иначе каждое Если стало бы вызовом.

Разбор идёт в два прохода, и это принципиально. Сначала по всему файлу собираются объявления, потом по телам процедур ищутся вызовы. Однопроходный вариант, который я написала первым, ломается на первом же модуле: вызов процедуры, объявленной ниже по тексту, уходит в счётчик внешних обращений, и модуль показывает три внутренние связи там, где их девятнадцать. Во втором проходе имя вызова ищется среди собранных объявлений; если нашлось и это не самообъявление, в список связей добавляется пара «откуда - куда»; если не нашлось, растёт счётчик внешних обращений, и имя попадает в топ частых.

Обработчики событий платформы разбор помечает по началу имени: При, Обработка, Перед, После. Это список догадок; таблицы обработчиков платформы в разборе нет, и ниже видно, чем эта догадка плоха.

🧪 Прогон на учебном модуле

Проверяла скрипт на учебном модуле primer-modulya.bsl из вложения. Модуль объекта, 17 процедур и функций, логика намеренно запутана: проверка заполнения вызывается из пяти мест, цепочка сверки количества тянется на пять переходов, одна процедура не вызывается ниоткуда.

python call_graph.py primer-modulya.bsl --dot primer-graf.dot
Файл: primer-modulya.bsl
Объявлено процедур и функций: 17 (из них с Экспорт: 1)
Связей внутри модуля: 19
Вызовов внутри модуля с учётом повторов: 19
Обращений к платформе и другим модулям (в граф не входят): 19

Точки входа - обработчики событий (3): ОбработкаПроведения, ПриЗаписи, ПриОткрытии
Точки входа - экспортные методы (1): ПроверитьЗаполнение
Без входящих связей и без Экспорт (1): НайтиСтрокуПоКоду
Вызываются из 3 и более мест: ПроверитьЗаполнение (5)
Самая длинная цепочка (5 переходов): ОбработкаПроведения -> СформироватьДвижения -> ПроверитьЗаполнение -> ПроверитьТабличнуюЧасть -> ПроверитьСтрокуТЧ -> СверитьКоличество

Самые частые внешние обращения (топ-10):
  Сообщить: 6
  ЗначениеЗаполнено: 4
  СтрШаблон: 4
  МоментВремени: 1
  ЭтоНовый: 1
  Структура: 1
  ЗаписьЖурналаРегистрации: 1
  Формат: 1

Что из этого отчёта видно сразу:

  • Одна внешняя точка. Из 17 процедур экспортная одна - ПроверитьЗаполнение. Остальное внутренняя кухня, и это уже ограничивает радиус правки: снаружи модуль отдаёт одну функцию.
  • Внутренних связей и внешних обращений поровну, по 19. Модуль плотно работает с платформой: Сообщить, ЗначениеЗаполнено, СтрШаблон, запрос остатков. По одному этому числу оценивают, насколько модуль привязан к контексту, но не время работы.
  • Четыре точки входа, из них три - обработчики. ОбработкаПроведения, ПриЗаписи, ПриОткрытии вызываются платформой; вызовов в коде модуля у них нет, и в анализе их считают корнями.
  • ПроверитьЗаполнение вызывается из пяти мест. Порог в три входящих связи она перешла одна. Правка в ней отзовётся в пяти сценариях.
  • НайтиСтрокуПоКоду не вызывается ниоткуда и не экспортная. Либо мёртвая, либо вызывается извне модуля.
  • На конце самой длинной цепочки стоит запрос к виртуальной таблице остатков. Цепочка из пяти переходов ведёт к обращению к базе, и это первое место, которое стоит смотреть при разборе производительности.

💻 Граф в Graphviz

По ключу --dot скрипт пишет файл в формате Graphviz: 40 строк, из них 17 узлов и 19 связей. Устройство файла простое. Открывает его строка digraph module {, за ней rankdir=LR задаёт направление слева направо. Дальше идут строки узлов вида "ПроверитьЗаполнение" [fillcolor="#FDE68A", style="filled"]; и строки связей вида "ОбработкаПроведения" -> "ПроверитьЗаполнение";. Заливка узла зависит от числа входящих связей: три и больше - жёлтая, ни одной - серая, остальные белые. По этой заливке карту и читают: серые узлы слева - точки входа, жёлтый узел в середине - место, которое меняют осторожно, длинный хвост связей справа - цепочка проверок.

Картинка рисуется одной командой, сам Graphviz ставится отдельно.

dot -Tsvg primer-graf.dot -o primer-graf.svg

Если отдельный пакет ставить не хочется, тот же граф описывается текстом Mermaid и рисуется прямо в документации или в wiki проекта.

ОбработкаПроведения
↓
СформироватьДвижения
↓
ПроверитьЗаполнение
↓
ПроверитьТабличнуюЧасть
↓
ПроверитьСтрокуТЧ
↓
СверитьКоличество

Модуль занимает 191 строку, картинка по нему - 17 узлов и 19 связей. Читается она быстрее текста: хвост цепочки проверок виден сразу, без вычитывания сотни строк подряд.

🧭 Как читать граф

Читаю карту в четыре прохода, от дешёвого к дорогому.

Узлы без входящих связей. Серая заливка означает, что изнутри модуля процедуру никто не зовёт. Дальше два варианта: обработчик события или экспортный метод - это нормальная точка входа, и трогать её не надо. Всё остальное - кандидат в мёртвый код, но перед удалением имя ищут по всей выгрузке: процедура может вызываться из другого модуля, из строки Выполнить или из расширения. В учебном модуле такой узел один, НайтиСтрокуПоКоду.

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

Длинные цепочки. Цепочка на пять-шесть переходов означает пять-шесть уровней, которые надо держать в голове при отладке. Иногда это осмысленная иерархия, иногда следы правок: промежуточная функция появилась, чтобы обойти один вызов, и осталась. Склеивать уровни стоит тогда, когда промежуточная функция ничего не добавляет к смыслу.

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

🚧 Чего статический разбор не видит

Текстовый разбор дёшев ровно потому, что не разбирает синтаксис. Плата за это - слепые зоны.

  • Вызовы через строку. Выполнить("Проверить" + ИмяЧасти), Вычислить, вызов метода по имени из реквизита - для скрипта это текст в кавычках, и он вырезан вместе с литералами. Такие места ищутся глазами по выгрузке.
  • Связи между модулями. Граф строится по одному файлу. Обращения к общим модулям попадают в счётчик внешних обращений, и по нему видно только их количество, но не адресат.
  • Обработчики определяются по началу имени. При, Обработка, Перед, После - догадка скрипта. Процедура ПривестиКНормальномуВиду попадёт в точки входа, хотя обработчиком не является. Список приходится просматривать глазами.
  • Расширения и заимствование. В расширении модуль-заимствование и директивы &Вместо, &После, &Перед связывают код расширения с основным модулем. Разбор одного файла эту связь не покажет: нужны обе стороны.
  • Время работы. Ни одна цифра отчёта не говорит о производительности. Сообщить: 6 означает шесть обращений к платформе в тексте; миллисекунд за этой цифрой нет.

Из этого списка следуют две привычки. Перед удалением «мёртвой» процедуры имя ищут по всей выгрузке, включая расширения. Перед выводами о скорости запускают замер: карта показывает, где смотреть, и не отвечает на вопрос, сколько это стоит в секундах.

📚 Что уже есть по теме

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

1C:EDT, панель «Иерархия вызовов». Встроенная панель показывает, кто вызывает метод и что вызывает он, по конкретному методу проекта. Работает разбором кода: понимает обращения через точку и типы. Карту по всему модулю разом она не рисует, зато не ошибается на вызовах через строку там, где их видно статически.

Отладчик конфигуратора и «Стек вызовов». Точка останова на входе в подозрительную процедуру даёт цепочку вызовов живого сценария. Точность здесь максимальная: за цепочкой стоит факт выполнения. Цена - покрытие: чтобы обойти модуль с десятками ветвлений, нужно прогнать столько сценариев, сколько ветвей, а для разбора производительности ещё и замерить время на каждом уровне.

Обработка «Карта вызовов для проектов 1С» на Infostart (публикация 78976, автор stal76). Строит карту вызовов по объектам, модулям и методам конфигурации и выгружает результат для отрисовки в Graphviz. В описании заявлены платформы 8.1 и 8.2, обработка платная; для 8.3 её нужно проверять отдельно.

Отдельно отмечу опубликованную статью 2798216 про граф знаний конфигурации: там связи между объектами конфигурации - справочниками, документами, регистрами. Здесь уровень ниже: процедуры внутри одного модуля. Для первого знакомства с чужим модулем второй разрез полезнее, потому что показывает, с какой процедуры начинать чтение.

📎 Файл к статье

Во вложении три файла и описание к ним.

  • call_graph.py - скрипт разбора. Нужен Python 3.8 и старше, сторонних библиотек нет, платформа не нужна.
  • primer-modulya.bsl - учебный модуль, на котором проверялся скрипт: 17 процедур, пять вызовов проверки заполнения, цепочка на пять переходов, одна процедура без вызовов.
  • primer-graf.dot - граф учебного модуля, построенный скриптом. Открывается просмотрщиком DOT или командой dot -Tsvg.
  • README.md - что проверено и что осталось непроверенным. Отдельно: учебный модуль не компилировался на платформе, для запуска нужна база с регистром накопления и документом с табличной частью Товары.

🏁 Итог

Порядок работы с незнакомым модулем укладывается в три шага. Выгружаю конфигурацию в файлы и забираю нужный .bsl. Прогоняю по нему скрипт и читаю отчёт: точки входа, горячие узлы, цепочки, узлы без связей. Открываю граф и смотрю, откуда начинать чтение.

Дальше начинается работа, которую скрипт за разработчика не сделает. Мёртвый узел перед удалением проверяется поиском по выгрузке. Кандидаты на оптимизацию проверяются замером; количество входящих связей для этого не годится. Разбиение длинной процедуры заканчивается прогоном сценариев. Карта показывает, где смотреть, и экономит на этом часы чтения; выводы о поведении кода она не выдаёт.

 
Нинель Адольевна Щербакова
Нинель Адольевна Щербакова (Ninel_S)
Архитектор • SRE & DevOps инженер • HighLoad 1С
Автор 30 технических публикаций на Infostart. Разработчик NOPik, SRE-Suite-for-1C и мультиагентных ассистентов для экосистемы 1С:Предприятие.

Вступайте в нашу телеграмм-группу Инфостарт

граф вызовов разбор модуля 1С статический анализ BSL рефакторинг Python Graphviz мёртвый код технический долг

См. также

Рефакторинг и качество кода Разработчик 1С 8.3 Бесплатно (free)

Как перевести технический долг в деньги: пример с реквизитом в документе, скрипт git_hotspots.py для поиска горячих модулей по истории Git и формулировки для разговора с руководителем. Суммы в примерах условные.

01.10.2026    523    Ninel_S    0    

3

Нейросети Рефакторинг и качество кода Разработчик 1С 8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Россия Бесплатно (free)

Коммерческое расширение для БП, УНФ и УТ написали ИИ-агенты, а я проверял. Семь случаев, когда ИИ уверенно ошибся, и что его поймало: правило «проверка обязана хоть раз покраснеть», второй ИИ-ревизор, тесты под живым пользователем. Плюс конвейер, на котором сборка идёт 20 секунд, а ядро тестов — полторы минуты.

30.09.2026    731    deda    4    

3

Рефакторинг и качество кода Разработчик 1С 8.3 1С 8.5 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Знакомая последовательность. Внешний отчет на СКД: модуль объекта на две тысячи строк, девять текстов запросов, три набора данных со связями. Переделываю под другую базу, собираю ERF, прогоняю пакетную проверку конфигуратором, чисто. Отдаю. Через двадцать минут приходит скриншот: «Переменная не определена». Правлю, пересобираю, отдаю. Через двадцать минут второй: «Не задано значение параметра». Два круга через живого человека ради двух ошибок, каждая из которых воспроизводится на той же машине за три секунды. Если знать, чем ее воспроизводить. Воспроизводит ее COM-коннектор, и дальше вся статья про то, как из него собрать проверку, которая умеет падать.

28.09.2026    392    KonMa    0    

2

Рефакторинг и качество кода Разработчик 1С 8.3 1С:Управление торговлей 11 Россия Бесплатно (free)

8 приёмов за 10 минут: перестаньте прокручивать общий модуль на три тысячи строк как ленту в соцсети. Outline, #Область и фильтр - и вы уже в нужной процедуре, а не на строке «где-то внизу».

25.09.2026    1725    aleksandrboldyusov    7    

16

Перенос данных 1C Рефакторинг и качество кода Разработчик 1С 8.3 Бесплатно (free)

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

24.09.2026    492    nedomolkov.ivan    0    

1

Рефакторинг и качество кода Обновление 1С Разработчик 1С 8.3 Бесплатно (free)

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

22.09.2026    670    1c-izh    0    

5

Рефакторинг и качество кода Тестирование QA Разработчик Бесплатно (free)

Штатная страховка внутри цепочки обработки умеет прятать дефекты того шага, который стоит перед ней. У нас так и вышло: валидатор чинил результат постфактум, на выходе всё выглядело корректно, и никто не видел, что предыдущий шаг молча теряет данные. Вылезло это только на независимой проверке чужими глазами. Разбираю, чем инвариант отличается от сценарного теста и почему обычное умножение вытащило дефект из красивой метрики 0,997. Отдельно про 13 дублей, которые приехали из источника ещё до всякой обработки, и про две находки, которые оказались вообще не моими: они жили в эталонной реализации, откуда я списывал логику. Вторая часть про лимит выхода модели: почему обрезка ответа по длине это тихий ноль в мониторинге и как смена формата на дельты уронила выход до 4 951 токена. Есть отклонённые гипотезы и честный список того, чего мы так и не померили.

21.09.2026    554    nedomolkov.ivan    2    

1

WEB-интеграция Рефакторинг и качество кода Системный администратор Разработчик 1С 8.3 Бесплатно (free)

Я сел проверять внутренний поисковый сервис по коду: можно ли доверять ему в автоматическом режиме. Сверка с обычным текстовым поиском по файлам дала 261 из 261, 264 из 264 и 182 из 182 совпадений, разбор структуры файла - 318 функций из 318. Стопроцентная точность. Этот же замер и вскрыл, что опираться на сервис нельзя: искал он безупречно, только совсем не в том месте, которое я ему называл. Внутри разбор трёх дефектов, сложившихся в один тихий отказ: аргумент, проглоченный без ошибки; умолчание, выставленное когда-то наугад; снимок данных, у которого в ответе не указан возраст. Плюс регулярное задание, которое вся команда считала работающим и которого не существовало никогда. Перенос на 1С прилагается: готовый цикл проверки, после которого HTTP-сервис перестаёт молча принимать мусор.

21.09.2026    549    nedomolkov.ivan    0    

0
Для отправки сообщения требуется регистрация/авторизация