Чёрный пояс 1С. Мёртвый кэш и утечка памяти rphost | infolimp.ru

Чёрный пояс 1С. Мёртвый кэш и утечка памяти rphost: алгоритм расследования от технологического журнала до дампа WinDbg

23 августа 2026 · infolimp.ru · Чёрный пояс 1С

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

1. Архитектура памяти 1С: рабочие процессы, сеансы и метрики

Основной исполнитель кода и потребитель памяти на сервере приложений - процесс rphost. Он исполняет серверный BSL-код, управляет контекстами вызовов, кэширует скомпилированные модули и обрабатывает фоновые задания. Ошибочно считать его единственным виновником: в кластерах с активным полнотекстовым поиском и большим числом параллельных сеансов не реже накапливает утечку rmngr - менеджер кластера, который кэширует сеансовые данные и держит блокировки; профиль его памяти стоит снимать отдельно, не только по rphost.

Не путайте утечку с прогревом: после рестарта службы 1С агрессивно кэширует скомпилированные модули и метаданные - линейный рост Private Bytes в первые часы работы это штатный прогрев, а не утечка. О реальной утечке говорят, только когда рост не останавливается после прогрева и не снижается при падении пользовательской нагрузки.

Для аудита разделяют три системные метрики процесса:

2. Что такое «мёртвый кэш» и типовые источники удержания

Мёртвый кэш - структуры данных и объекты платформы, которые уже завершили полезную работу, но не могут быть освобождены сборщиком из-за активных входящих ссылок: удержания контекста сеанса, глобальных переменных, невыгруженных форм или кэша модулей.

Объект / механизмГде возникаетМеханика утечки и риски
Временное хранилищеФоновые обмены, передача файлов, отчётыИспользование ПоместитьВоВременноеХранилище без передачи UUID формы - данные удерживаются в памяти до завершения сеанса.
Модули с повторным использованиемОбщие серверные модули (кэш на время сеанса)Передача мутабельных структур или ссылок на контексты в параметры функции; кэширование больших таблиц.
Управляемые формыАРМ, открытые суткамиНакопление данных в реквизитах формы без очистки, хранение тяжёлых коллекций в клиент-серверном контексте.
Фоновые заданияМассовая обработка данных, регламентные загрузкиОбработка выборок в цикле без пачек (батчей), накопление транзакционного кэша объектов без периодической фиксации.
Циклические ссылкиСложные вложенные структуры, деревьяВзаимные ссылки объектов друг на друга (Структура → Массив → Структура), препятствующие обнулению счётчика ссылок.
Пулы сеансов HTTP-сервисовИнтеграционные шлюзы, REST APIСеанс HTTP-сервиса не уничтожается после ответа, а засыпает для переиспользования - мутабельные переменные и временное хранилище без явной очистки остаются в rphost. Особенно критично при тяжёлых JSON-пайплайнах (подготовка данных для RAG-ассистентов, поисковых API).
COM-объектыОбмен с Excel, внешние коннекторыНеконтролируемое создание Excel.Application и подобных объектов без явного вызова методов закрытия и обнуления переменных - процесс COM-сервера остаётся висеть в памяти хоста.

3. Анализ технологического журнала: локализация мест утечек

Технологический журнал (ТЖ) позволяет точно выявить строчку BSL-кода, серверный контекст или сеанс, вызвавший аномальный расход памяти, без остановки рабочего процесса. Метрика расхода фиксируется в свойствах Memory (выделенная память за операцию, в байтах) и MemoryPeak событий CALL, SCALL и событий обращения к СУБД (DBMSSQL для MS SQL Server, DBPOSTGRS для PostgreSQL).

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
  <dump create="false"/>
  <log location="C:\LOGS\1C_Memory_Trace" history="48">
    <!-- Фиксация серверных вызовов с расходом памяти более 100 МБ -->
    <event>
      <eq property="name" value="CALL"/>
      <gt property="Memory" value="104857600"/>
    </event>
    <event>
      <eq property="name" value="SCALL"/>
      <gt property="Memory" value="104857600"/>
    </event>
    <property name="all"/>
  </log>
</config>

В сформированном логе анализируются ключевые атрибуты: Context - стек вызова методов встроенного языка, где произошёл скачок выделения памяти; Usr / SessionID - пользователь или номер регламентного фонового задания; Memory / MemoryPeak - точный объём запрошенной оперативной памяти за время вызова.

4. Снятие и анализ дампов памяти процесса rphost

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

Внимание: снятие полного дампа памяти (Full Userdump) процесса размером в десятки гигабайт приостанавливает выполнение потоков процесса на время записи на диск. На продуктивных серверах предварительно исключите рабочий процесс из балансировки кластера.

Инструментарий снятия дампа:

Анализ нативного дампа: rphost - нативное C++ приложение, поэтому применяются отладчики WinDbg, DebugDiag Analysis (Windows) или Heaptrack / GDB (Linux). Но у самостоятельного анализа есть жёсткий потолок.

Предел самостоятельного анализа: фирма «1С» не публикует PDB-символы rphost, поэтому стек вызовов внутри платформенного кода WinDbg покажет только сырые шестнадцатеричные адреса, а не имена функций и структур BSL - транслировать их обратно в конкретную строчку конфигурации самостоятельно нельзя. Команды выше надёжно покажут фрагментацию кучи и общее распределение памяти, но если рост уходит внутрь самой платформы (а не в объекты, которые держит ваш код), дамп нужно отправлять в официальную техподдержку 1С - только у них есть символы и исходники для точной диагностики.

5. Временное хранилище: правила безопасной работы

Неправильная работа с временным хранилищем - самая частая причина мёртвого кэша в длительных пользовательских сеансах.

// АНТИПАТТЕРН: данные привязаны к сеансу,
// будут удерживаться в памяти rphost до полного выхода пользователя из системы
АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаБольшихДанных);

// ПАТТЕРН: передан УникальныйИдентификатор контекста формы -
// платформа автоматически удалит данные при закрытии серверного контекста формы
АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаБольшихДанных, ЭтаФорма.УникальныйИдентификатор);

// ПАТТЕРН: явное освобождение памяти на сервере после завершения обработки
УдалитьИзВременногоХранилища(АдресХранилища);

6. Фоновые задания и транзакционный кэш

При обработке больших объёмов данных в цикле фонового задания платформа неявно кэширует считываемые и модифицируемые объекты. Если транзакция остаётся открытой или обработка идёт единым монолитным куском, рабочий процесс быстро исчерпывает лимиты памяти. Батчинг решает проблему памяти, но код без перехвата исключений оставляет зависшую транзакцию при первой же ошибке в пачке - и это уже не утечка памяти, а Lock timeout на весь кластер. Оборачивайте батч в Попытка/Исключение с гарантированным откатом:

// Обработка массивов данных пачками (батчами) с защитой от зависшей транзакции
РазмерПачки = 500;
Счётчик = 0;

НачатьТранзакцию();
Попытка
    Пока Выборка.Следующий() Цикл

        Объект = Выборка.ПолучитьОбъект();
        // ... модификация данных объекта ...
        Объект.Записать();

        Счётчик = Счётчик + 1;
        Если Счётчик % РазмерПачки = 0 Тогда
            ЗафиксироватьТранзакцию(); // сброс транзакционного кэша и блокировок
            НачатьТранзакцию();
        КонецЕсли;

    КонецЦикла;

    Если ТранзакцияАктивна() Тогда
        ЗафиксироватьТранзакцию();
    КонецЕсли;

Исключение
    // Гарантированный откат - иначе зависшая транзакция держит блокировки
    // и кэш до таймаута, а не до конца цикла
    Если ТранзакцияАктивна() Тогда
        ОтменитьТранзакцию();
    КонецЕсли;
    ЗаписьЖурналаРегистрации("МассоваяОбработка", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    ВызватьИсключение;
КонецПопытки;

7. Модули с повторным использованием значений

Кэш общих модулей с параметром ПовторноеИспользование = НаВремяСеанса или НаВремяВызова сохраняет возвращённые значения в памяти сеанса.

Правила проектирования кэширующих модулей:

8. Предотвращение и архитектурный контроль

Для стабильности кластера и предотвращения аварий из-за утечек памяти - трёхуровневая стратегия:

  1. Ограничение лимитов на уровне кластера 1С: параметр «Безопасный расход памяти за один вызов» (например, 2-4 ГБ в зависимости от базы), параметр «Допустимый объём памяти рабочих процессов», плановый перезапуск процессов по интервалу («Интервал перезапуска рабочих процессов») - исключительно как стабилизирующая мера на время исправления дефектов в коде, не как постоянное решение.
  2. Автоматический аудит BSL-кода: статический анализатор (Sonarqube с плагином 1С / BSL Language Server) с правилами проверки на вызовы ПоместитьВоВременноеХранилище без UUID и на передачу мутабельных параметров в кэшируемые функции.
  3. Проактивный мониторинг: алертинг (Zabbix/Prometheus) по порогу Private Bytes процесса rphost и сбор событий технологического журнала с фильтром Memory > 100MB.

Чек-лист аудита утечек памяти

Глоссарий

Чёрный пояс 1С · Практический алгоритм для инженеров, ведущих кластер 1С в проде

Проверьте свой уровень на платформе токенов infolimp.ru - анонимно, без резюме. Архитектурные кейсы уровня Чёрного пояса засчитываются в историю токена.

Создать токен →