Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 8 общая

Освобождение памяти при выходе из процедуры

Освобождение памяти при выходе из процедуры
Я
   paramedic
 
15.12.20 - 10:49
Народ, я хочу уточнить один момент.
Должна ли 1С-ина освобождать память, выделенную на локальные переменные процедуры при выходе из нее?
У меня получается, что память в платформе 8.3.18 освобождается только после полного завершения серверного вызова.
В 8.3.16 такого поведения не замечал.
   polosov
 
1 - 15.12.20 - 10:51
(0) Не должна. Сборщик мусора сам запускается.
   ДНН
 
2 - 15.12.20 - 10:53
(0) Если это локальные переменны, то должна. Никакого сборщика мусора в 1с нет
   polosov
 
3 - 15.12.20 - 10:55
(2) Механизм подсчета ссылок не всегда нормально работает. По-любому должна быть процедура освобождения памяти.
   polosov
 
4 - 15.12.20 - 10:56
(2) А ну да, прочитал. Только тупой подсчет ссылок.
   ДенисЧ
 
5 - 15.12.20 - 11:04
(4) А что, "тупой подсчёт ссылок" не есть один из алгоритмов сборки мусора?

(0) Явно определяй переменные в начале процедуры. Ссылочные и объектные типы зануляй после использования. И очень много памяти будет освобождаться.
   paramedic
 
6 - 15.12.20 - 11:11
Циклических ссылок нет. НАбросал тестовый пример: создание большой таблицы значений внутри процедуры. Циклически ее вызываю и получаю переполнение памяти на серверный вызов.
Причем в конце процедуры принудительно делаю ТЗ.Очистить(); ТЗ = Неопределено.
Высвобождается около половины памяти по счетчику в консоли сервера.
Реально память сервера не расходуется. Я легко получал по счетчику памяти на два процесса больше, чем есть памяти физически.
   Cyberhawk
 
7 - 15.12.20 - 11:25
(6) Смирись - даже если память будет освобождена (помечена доступной), то ты этого можешь никак не увидеть
   paramedic
 
8 - 15.12.20 - 11:50
(7) Не могу )) У меня есть загрузка большого объема информации в регламентном задании. На 16 платформе все работало, а на 18 - падает по нехватке памяти ((
   polosov
 
9 - 15.12.20 - 11:59
(5) Да, алгоритм. Как бы сборки. Но тупой.
   ДенисЧ
 
10 - 15.12.20 - 12:15
(8) Ставь 64бит
   paramedic
 
11 - 15.12.20 - 12:18
(10) Веско и на полкилометра мимо ))
   paramedic
 
12 - 15.12.20 - 12:20
(10) У меня 64ГБ на сервере, по мониторингу заполнено 25-35 ГБ, а 1С считает, что на один вызов потребляет более 50 ГБ и падает.
   ДенисЧ
 
13 - 15.12.20 - 12:20
(12) Ну что тебе сказать... Ставь 128бит.
Или консерваторию начинай перестраивать.
   H A D G E H O G s
 
14 - 15.12.20 - 12:22
(12) Покажи хоть тестовый пример.
   paramedic
 
15 - 15.12.20 - 12:24
(13) Хрен перестроишь... Часть данных падает как json, часть как xml, часть как xls. И все по 90-100 тыс. записей, которые надо разобрать, сопоставить, дорассчитать...
   H A D G E H O G s
 
16 - 15.12.20 - 12:24
Вон, на партнерке выяснили, что 8.3.18 потребляет на 40% больше стековой памяти на вызов метода, чем 8.3.17.
Но это про стек.
   Dmitrii
 
17 - 15.12.20 - 12:25
(6) >> Циклических ссылок нет. ...создание ... процедуры. Циклически ее вызываю.

1. ты уверен, что тут нет противоречия? Даже если фактической утечки нет, 1С почему-то считает, что есть. Косяк либо в платформе, либо в твоём коде.
2. Может поменять подход и не создавать каждый раз новую ТЗ внутри этой процедуры, а передавать её на вход. А внутри процедуры только заполнять ТЗ и очищать методом ТЗ.Очистить() в конце процедуры.
   paramedic
 
18 - 15.12.20 - 12:25
(14)
&НаСервере
Процедура Проверочная()
    
    Тз = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Документ");
    ТЗ.Колонки.Добавить("Контрагент");
    ТЗ.Колонки.Добавить("Товар");
    ТЗ.Колонки.Добавить("ЦенаПродажи");
    ТЗ.Колонки.Добавить("Количество");
    ТЗ.Колонки.Добавить("Дата");
    ТЗ.Колонки.Добавить("Склад");
    ТЗ.Колонки.Добавить("Организация");
    ТЗ.Колонки.Добавить("УстановленнаяЦена");
    ТЗ.Колонки.Добавить("ВидЦен");
    
    ТекстЗапроса = "ВЫБРАТЬ
|    РасходТовараТовары.Ссылка КАК Ссылка,
|    РасходТовараТовары.Товар КАК Товар,
|    РасходТовараТовары.Цена КАК Цена,
|    РасходТовараТовары.Количество КАК Колво,
|    РасходТовараТовары.Ссылка.Дата КАК Дата,
|    РасходТовараТовары.Ссылка.Склад КАК Склад,
|    РасходТовараТовары.Ссылка.Организация КАК Организация,
|    ЦеныТоваровСрезПоследних.Цена КАК УстановленнаяЦена,
|    ЦеныТоваровСрезПоследних.ВидЦен КАК ВидЦен
|ИЗ
|    Документ.РасходТовара.Товары КАК РасходТовараТовары
|        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныТоваров.СрезПоследних КАК ЦеныТоваровСрезПоследних
|        ПО (РасходТовараТовары.Товар = ЦеныТоваровСрезПоследних.Товар)";
    Запрос = Новый Запрос;
    Запрос.Текст = ТекстЗапроса;
    Выборка = Запрос.Выполнить().Выбрать();
    
    Для Счетчик=1 По 5000 Цикл
        Выборка.Сбросить();
        Пока Выборка.Следующий() Цикл
            Стр = ТЗ.Добавить();
            Стр.Документ = Выборка.Ссылка;
            Стр.Контрагент = Выборка.Ссылка.Покупатель;
            Стр.ТОвар = Выборка.Товар;
            Стр.ЦенаПродажи = Выборка.Цена;
            Стр.Количество = Выборка.Колво;
            Стр.Дата = Выборка.Дата;
            Стр.Склад = Выборка.Склад;
            Стр.Организация = Выборка.Организация;
            Стр.УстановленнаяЦена = Выборка.УстановленнаяЦена;
            Стр.ВидЦен = Выборка.ВидЦен;
        КонецЦикла;
    КонецЦикла;
    
    ТЗ.Очистить();
    ТЗ = Неопределено;
КонецПроцедуры

&НаСервере
Процедура Команда1НаСервере()
    // Вставить содержимое обработчика.

    Для Сч = 1 По 100 Цикл
        Проверочная();
    КонецЦикла;
    
    
КонецПроцедуры

&НаКлиенте
Процедура Команда1(Команда)
    Команда1НаСервере();
КонецПроцедуры

Пример сделан на демобазе. Один вызов Проверочная() по счетчику потребляет 13 ГБ, освобождает 6.
   timurhv
 
19 - 15.12.20 - 12:26
(12) в свойствах "Критический объем памяти процессов" поставьте -1 и увеличьте файл подкачки. Вроде с каких-то версий 8.3.17 и 8.3.18 лицензию КОРП уже не просит.
   rphosts
 
20 - 15.12.20 - 12:26
(12) что-ж ты за хрень грузишь-то?
   rphosts
 
21 - 15.12.20 - 12:27
(18) а если добавить
Запрос = неопределено;
Выборка = Неопределено;
   arsik
 
22 - 15.12.20 - 12:28
(18) (21) С языка снял.
   polosov
 
23 - 15.12.20 - 12:28
(18)Попробуй типизировать поля ТЗ перед использованием.
   timurhv
 
24 - 15.12.20 - 12:29
(12) (19) и падать должно при 60Гб, вы проверяли на старых релизах про 50Гб? Вроде давно увеличили до 95% от ОЗУ с 80% с параметром 0.
   paramedic
 
25 - 15.12.20 - 12:33
(20) Прайсы поставщиков... По ним рассчитываю наши цены, выставляю цены поставщиков.
(24) На 16 релизе не видел такого потребления памяти по счетчику (именно по счетчику, а не реально).
(19) Требует КОРП...
   timurhv
 
26 - 15.12.20 - 12:38
(25) В этом году в описании убрали требование КОРП:
https://its.1c.ru/db/v8318doc#bookmark:cs:TI000000158
с 8.3.14 еще есть
https://its.1c.ru/db/v8314doc#bookmark:cs:TI000000158
В 8.3.15 вроде убрали с какого-то релиза. Но физически я не проверял, может звиздят.
   paramedic
 
27 - 15.12.20 - 12:40
(26) Любые счетчики ресурсов сервера требуют КОРП. Проверял и в ссылках это есть
   paramedic
 
28 - 15.12.20 - 12:42
(21) Один хрен. Освобождает ровно половину памяти. Еще раз оговорюсь: по счетчику. Реально такого потребления памяти нет.
   Kassern
 
29 - 15.12.20 - 12:52
(28) Попробуй через фоновые задания частями загружать данные, возможно поможет с памятью вопрос решить
   paramedic
 
30 - 15.12.20 - 13:00
(29) Не могу грузить частями - отдаются только полностью. Насчет дальнейших расчетов фоновыми можно попробовать, но это не на раз-два делается...
 
 Рекламное место пустует
   бомболюк
 
31 - 15.12.20 - 13:04
Стр.Контрагент = Выборка.Ссылка.Покупатель;

попробуй получать покупателя не через Ссылку, а в запросе, так точно будет быстрее, и я думаю, расход памяти тоже сократится.
   paramedic
 
32 - 15.12.20 - 13:14
(31) Вопрос "быстрее" не стоит. Убрал вообще этот столбец: выделение памяти с 13,3 ГБ за вызов Проверочная() сократилось до 13,1 ГБ. Ну просто ппц, как много ))
   ASU_Diamond
 
33 - 15.12.20 - 13:17
(32) а попробуй по одной колонке делать, посмотри где какой объем получается
Типизировать колонки пробовал, как в (23) рекомендовали?
   Фрэнки
 
34 - 15.12.20 - 13:21
И это еще хорошо, что после завершения серверного вызова память чистится.
   Dmitrii
 
35 - 15.12.20 - 13:22
Попробуй сделать так.


&НаСервере
Процедура Проверочная(ТЗ)
    
     ТекстЗапроса = "ВЫБРАТЬ
     |    РасходТовараТовары.Ссылка КАК Документ,
     |    РасходТовараТовары.Ссылка.Покупатель КАК Контрагент,
     |    РасходТовараТовары.Товар КАК Товар,
     |    РасходТовараТовары.Цена КАК ЦенаПродажи,
     |    РасходТовараТовары.Количество КАК Количество,
     |    РасходТовараТовары.Ссылка.Дата КАК Дата,
     |    РасходТовараТовары.Ссылка.Склад КАК Склад,
     |    РасходТовараТовары.Ссылка.Организация КАК Организация,
     |    ЦеныТоваровСрезПоследних.Цена КАК УстановленнаяЦена,
     |    ЦеныТоваровСрезПоследних.ВидЦен КАК ВидЦен
     |ИЗ  
     |    Документ.РасходТовара.Товары КАК РасходТовараТовары
     |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныТоваров.СрезПоследних КАК ЦеныТоваровСрезПоследних
     |        ПО (РасходТовараТовары.Товар = ЦеныТоваровСрезПоследних.Товар)";
    Запрос = Новый Запрос;
    Запрос.Текст = ТекстЗапроса;
    Выборка = Запрос.Выполнить().Выбрать();
    
    Для Счетчик=1 По 5000 Цикл
        Выборка.Сбросить();
        Пока Выборка.Следующий() Цикл
            ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), Выборка);
        КонецЦикла;
    КонецЦикла;
    
    ТЗ.Очистить();
КонецПроцедуры

&НаСервере
Процедура Команда1НаСервере()
    
    Тз = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Документ");
    ТЗ.Колонки.Добавить("Контрагент");
    ТЗ.Колонки.Добавить("Товар");
    ТЗ.Колонки.Добавить("ЦенаПродажи");
    ТЗ.Колонки.Добавить("Количество");
    ТЗ.Колонки.Добавить("Дата");
    ТЗ.Колонки.Добавить("Склад");
    ТЗ.Колонки.Добавить("Организация");
    ТЗ.Колонки.Добавить("УстановленнаяЦена");
    ТЗ.Колонки.Добавить("ВидЦен");

    Для Сч = 1 По 100 Цикл
        Проверочная(ТЗ);
    КонецЦикла;
    
КонецПроцедуры

&НаКлиенте
Процедура Команда1(Команда)
    Команда1НаСервере();
КонецПроцедуры


   Dmitrii
 
36 - 15.12.20 - 13:25
(31) (33) (23) Всё это справедливые замечания, но явно не эти проблемы являются ключевой причиной ошибки. Устранение этих замечаний не решит вопрос принципиально, а лишь поможет чуть-чуть сэкономить памяти и времени.
   polosov
 
37 - 15.12.20 - 13:34
Можно логику формирования и работы с ТЗ вынести в обработку. В фоновом задании создавать экземпляр объекта обработки, формировать ТЗ, работать с ней  и грохать экземпляр обработки после использования. Может это более явно освободит память.
   бомболюк
 
38 - 15.12.20 - 13:43
Можно поинтересоваться: сколько примерно документов Документ.РасходТовара попадают в результат выборки в боевой базе?
   H A D G E H O G s
 
39 - 15.12.20 - 13:51
8.3.17 нормально сбрасывает память, кстати.
8.3.18 серверную ставить лениво
   paramedic
 
40 - 15.12.20 - 14:49
(39) 8.3.16 тоже. Косяк, похоже в 3.18
   paramedic
 
41 - 15.12.20 - 14:52
(38) Пример сделан в демо базе, от 1С. Запрос возвращает 1118 строк. В боевой базе совсем другая задача, но принцип работы тот же - обработка больших таблиц, дергание информации из запросов плюс создание документов установки цен. УТ 11.
   бомболюк
 
42 - 15.12.20 - 15:03
Я вот почему спросил: при выполнении 
Стр.Контрагент = Выборка.Ссылка.Покупатель;
неявно происходит получение из БД и кеширование в памяти объекта Выборка.Ссылка, то есть полностью документа РасходТовара (а это немало), которое, предполагаю, сохраняется как минимум до конца вызова процедуры. Ну и если таких документов много - это отъест много памяти, и, как мне представляется, программист на это повлиять не может. То есть утечка не там, где ты ищешь, и, поэтому, тест делаешь неправильно.

Попробуй взглянуть на задачу с этой точки зрения.
   paramedic
 
43 - 15.12.20 - 15:07
(42) А прочитать (32) ?
Удаление из запроса и таблицы столбца Документ (Ссылка) в дополнение к "Контрагент" уменьшает "выделяемую" память до 11,4 ГБ. Очистка - так же около половины.
   paramedic
 
44 - 15.12.20 - 15:20
(43) А утечка именно там, где и ищу: при выходе из процедуры не освобождаются ресурсы, выделенные на локальные переменные. Вопрос о РАЗМЕРЕ выделенной памяти я не поднимал, хотя он тоже весьма интересен: на боевой базе счетчики по всем соединениям легко показывают 120 ГБ при общем объеме памяти сервера (вместе с подкачкой) 96 ГБ. Реальное же выделение памяти на ВСЕ процессы сервера занимает 28-35 ГБ.
Похоже проблема может быть не в реальном выделении памяти, а в изменившейся методике подсчета этого выделения. Например: считается вся теоретическая память, которая может быть выделена под объект когда он весь, со всеми связанными загружен в память, а сбрасывается со счетчика только реально выделенная. Но это так, гадание на кофейной гуще.
   hhhh
 
45 - 15.12.20 - 15:24
(43) вот тут какая-то фигня
      Пока Выборка.Следующий() Цикл
            Стр = ТЗ.Добавить();

делай

ТЗ = Запрос.Выполнить().Выгрузить();
   paramedic
 
46 - 15.12.20 - 15:26
(45) Мне НЕ НАДО этого делать. Мне НАДО использовать механизм, который используется в реальности. В реальности я не получаю исходные данные запросом из базы.
   H A D G E H O G s
 
47 - 15.12.20 - 15:28
(46) Вы прям меня вынуждаете развернуть сервер 8.3.18
   paramedic
 
48 - 15.12.20 - 15:30
(47) Чтобы посмотреть результат? Тогда для полной аутентичности его разворачивать надо на centos ))
   H A D G E H O G s
 
49 - 15.12.20 - 15:44
(48) Разворачивать на... чём?
   H A D G E H O G s
 
50 - 15.12.20 - 15:47
(48) На самом деле, я в курсе, что такое centos, но просто высокомерно считаю, что unix системам не место в мире 1С
   polosov
 
51 - 15.12.20 - 15:49
(50) Напиши в фирму 1С об этом. А то пацаны то не в курсе.
   paramedic
 
52 - 15.12.20 - 15:52
(50) Я даже работаю периодически на клиенте под centos )) особых косяков не заметил.
(51) Вечером хочу сделать такой же тест под 8.3.16 (18 платформа милостиво ставится в свою папочку и теперь достаточно поменять скрипт запуска) и отправить результат и по этой платформе.
   H A D G E H O G s
 
53 - 15.12.20 - 15:53
Поставил 8.3.18, все нормально освобождает. Под виндой.
   H A D G E H O G s
 
54 - 15.12.20 - 15:54
(51) Это проблемы 1С.
   H A D G E H O G s
 
55 - 15.12.20 - 15:54
(53) Режим совместимости 8.3.15.
   paramedic
 
56 - 16.12.20 - 10:45
(55) На 8.3.16 обработка отрабатывает полностью и не падает. Память после выхода из процедуры высвобождается практически полностью.
Все-таки это дело в счетчиках памяти. В 1С написал.
   rphosts
 
57 - 16.12.20 - 18:34
(50) +1 но как ОС для Постгри линухи хороши!
   Фрэнки
 
58 - 16.12.20 - 19:11
А я вот все-таки злорадно предвкушаю, что все-таки уже довольно скоро дойдет до того, что для 1С будут говорить, что ненормально как раз ставить ее на винду.

Хотя понятно, что для этого нужно дождаться хотя нормальной работы конфигуратора в линукс.

Но, по всей видимости, эта самая нормальная работа появится тогда, когда 1С дорастет наконец до установки репозитория для обновлений и платформы и конфигураций.
Кстати, интересно, у кого-то в линуксовой среде из режима предприятия происходит обновление конфигураций или это пока еще не работает?


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.