![]() |
|
Нехватка памяти | ☑ | ||
---|---|---|---|---|
0
Air777
17.09.11
✎
15:27
|
По мотивам
v8: Нехватка памяти Платформа 8.2.13.219 Код: .... Для Каждого СтрокаТаблицы Из ТаблицаДокументов Цикл Ссылка=СтрокаТаблицы.Ссылка; Объект=Ссылка.ПолучитьОбъект(); Объект=Неопределено; КонецЦикла; ТаблицаДокументов=Неопределено; ... Течет память. Достигая потолка в 1.5 Гб клиент падает. Как бороться??? |
|||
1
Darych
17.09.11
✎
15:31
|
гламурный код
|
|||
2
Jolly Roger
17.09.11
✎
15:32
|
(0) это, скорее, мозги текут...
|
|||
3
Air777
17.09.11
✎
15:37
|
(2) Вот зачем сразу хамить?
Разумеется это не кусок реального кода, а пример показывающий место утечки. |
|||
4
ОбычныйЧеловек
17.09.11
✎
15:43
|
(0) Уверен, что утечка памяти именно в этом месте происходит?
|
|||
5
Jolly Roger
17.09.11
✎
15:44
|
(3) ну дык, какой вопрос - такой и ответ. в приведенном коде никакой утечки нет...
|
|||
6
Air777
17.09.11
✎
15:45
|
(4)На 100% Перепроверено многократно
Объект=Неопределено; не выгружает объект из памяти Даже закрытие обработки тоже не высвобождает память как в ветке из (0) |
|||
7
ОбычныйЧеловек
17.09.11
✎
15:48
|
(6) я согласен с (5) о том, что в приведенном коде утечки быть не должно. То что "Объект=Неопределено;
не выгружает объект из памяти" в данном случае ни о чем не говори, откуда вызывается данный код, в транзакции выполняется? |
|||
8
ОбычныйЧеловек
17.09.11
✎
15:49
|
хочешь освободить память, просто сверни\разверни 1ску - память освободится.
|
|||
9
ОбычныйЧеловек
17.09.11
✎
15:50
|
пролемка у тебя явно где то в другом месте - надо код полостью смотреть
|
|||
10
Air777
17.09.11
✎
15:52
|
Процедура КнопкаВыполнитьНажатие(Кнопка)
Выборка=Документы.Реализация.Выбрать(Дата("20110801"),); Пока Выборка.Следующий() Цикл Сообщить(Выборка.Ссылка.Номер); Объект=Выборка.ПолучитьОбъект(); Объект=Неопределено; КонецЦикла; Выборка=Неопределено; КонецПроцедуры Демонстрирует проблемму. (9) действительно помагает!!! Как бы этим еще управлять? |
|||
11
Air777
17.09.11
✎
15:57
|
(10) Объем используемой памяти проверяю диспетчером задач
При работе кода используемая память непрерывно ростет, и да (это прям находка) действительно (!!!) когда сернуть/развернуть окно она высвобождается. Искренне верил что она должна освобождаться сразу же в процессе работы процедуры ну или по ее завершению или хотя бы по закрытию обработки ан НЕТ! |
|||
12
Jolly Roger
17.09.11
✎
16:00
|
и как только у людей перепроведение документов работает? в цикле получают тысячи объектов...
|
|||
13
ОбычныйЧеловек
17.09.11
✎
16:00
|
(11) К сожалению не могу поверить твой код на утечку памяти (дома нету 1Ски), но утечки быть в этом коде не должно (кстати выборку лучше запросом делать).А на счет свертки\разветки приложения - ты можешь это делать в момент выполнения обработки (в диспетчере на процессе говоришь свернуть и вуаля память очищена :))
|
|||
14
shuhard
17.09.11
✎
16:03
|
(13)[в диспетчере на процессе говоришь свернуть]
угу, в час ночи резко ворваться в серверную и отнять у шедулера мышь |
|||
15
Air777
17.09.11
✎
16:06
|
(12) возьми код из (10) воткни в новую пустую обработку и убедись воочию. Потом поговорим.
|
|||
16
Jolly Roger
17.09.11
✎
16:22
|
(15) э нет, спасибо. нафтыкался уже...
|
|||
17
shuhard
17.09.11
✎
16:23
|
(15) у меня каждую ночь вот такая обработочка документы перепроводит, не падает, документов много, УПП
Если Не Константы.ИспользоватьФоновоеПерепроведение.Получить() Тогда Возврат; КонецЕсли; ШаблонПодзапроса = " |ВЫБРАТЬ | Ссылка КАК Регистратор, | Дата КАК Дата |ИЗ Документ.%ИмяДокумента% |ГДЕ | Дата >= &ДатаНачала И Дата <= &ДатаОкончания | И Проведен |ОБЪЕДИНИТЬ ВСЕ"; ТекстЗапроса = ""; //Текст запроса складывается объединением из идентичных запросов по документам, которые являются регистраторами для регистра ДокументыТребующиеДопроведения РегистрМД = РегистрыСведений.ДокументыТребующиеДопроведения.СоздатьНаборЗаписей().Метаданные(); Для каждого ДокументМД из Метаданные.Документы цикл ТекстЗапроса = ТекстЗапроса + стрЗаменить(ШаблонПодзапроса,"%ИмяДокумента%", ДокументМД.Имя); КонецЦикла; //Уберем последнее ОБЪЕДИНИТЬ ВСЕ из текста запроса ТекстЗапроса = Лев(ТекстЗапроса, СтрДлина(ТекстЗапроса) - 14); ТекстЗапроса=ТекстЗапроса+ " Упорядочить ПО Дата,Регистратор"; Запрос=Новый Запрос; Запрос.Текст= ТекстЗапроса; // организуем цикл по дате, на каждый день отдельный запрос ДатаПерепроведения=Константы.ДатаСтартаПерепроведения.Получить(); Пока ДатаПерепроведения <=ТекущаяДата() Цикл Запрос.УстановитьПараметр("ДатаНачала",НачалоДня(ДатаПерепроведения)) ; Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаПерепроведения)); // собственно запрос ТЗ=Запрос.Выполнить().Выгрузить(); #Если Клиент Тогда мКоличествоДокументов = ТЗ.Количество(); мФормаПрогрессора = Неопределено; //Для небольшого количества документов не имеет смысл показывать форму прогрессора Если мКоличествоДокументов > 2 Тогда мФормаПрогрессора = ПолучитьОбщуюФорму("ХодВыполненияОбработкиДанных"); мФормаПрогрессора.НаименованиеОбработкиДанных = "Перепроведение"; мФормаПрогрессора.КомментарийОбработкиДанных = "Перепроведение"; мФормаПрогрессора.Значение = 0; мФормаПрогрессора.МаксимальноеЗначение = мКоличествоДокументов; мФормаПрогрессора.КомментарийЗначения = "Перепроведение ..."; мФормаПрогрессора.Открыть(); мНомерОбрабатываемогоДокумента = 0; КонецЕсли; #КонецЕсли // пробежимся по ТЗ // получим объект документа // проведем Для КАждого СтрокаТЗ Из ТЗ Цикл // вложенный цикл ТекДокумент = СтрокаТЗ.Регистратор; Попытка ДокОбъект = ТекДокумент.ПолучитьОбъект(); //ДокОбъект.ДополнительныеСвойства.Вставить("ЭтапПроведения", "Допроведение"); ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный); #Если Клиент Тогда ОбработкаПрерыванияПользователя(); Если мФормаПрогрессора <> Неопределено Тогда мНомерОбрабатываемогоДокумента = мНомерОбрабатываемогоДокумента + 1; мФормаПрогрессора.Значение = мНомерОбрабатываемогоДокумента; мФормаПрогрессора.КомментарийОбработкиДанных = "Перепроведение за " + Строка(Формат(ДатаПерепроведения,"ДЛФ=DD")); мФормаПрогрессора.КомментарийЗначения = "Перепроводится:" + мНомерОбрабатываемогоДокумента + " документ из " + мКоличествоДокументов; КонецЕсли; #КонецЕсли Исключение Сообщить("Сбой при проведении:"+Строка(ТекДокумент)+" "+Строка(ОписаниеОшибки())); КонецПопытки; // вложенный цикл() КонецЦикла; ДатаПерепроведения=ДатаПерепроведения+24*60*60; КонецЦикла; |
|||
18
Air777
17.09.11
✎
16:38
|
(17) да да за памятью понаблюдай как-нибудь... Судя по всему твои объемы не сопоставимы с моими поэтому ты и не натыкался на эти грабли.
(13) Все плохо. Вот нашел старую ветку с аналогичной ситуацией но для 7.7 Высвобождение памяти 1С 7.7 Пост №14: Сворачивание приложение не уменьшает потребление памяти 1С. То, что в диспетчере задач памяти отображается меньше, просто означает, что при сворачивании виндоус по максимуму уменьшает "workset" процесса. Т.е. множество страниц процесса, находящихся в физической памяти. Фактически, память 1С просто выгружается в файл подкачки. Если включить в диспетчере отображение еще и виртуальной памяти, то в этой колонке объем памяти уменьшаться не будет (скорее всего). Проверил у себя на 8.2 - ВСЕ ТАК ЖЕ память действительно высвобождается однако ВИРТУАЛЬНАЯ память остается НЕИЗМЕННОЙ!!! Блин что же делать?! |
|||
19
shuhard
17.09.11
✎
16:46
|
(18) как ни странна, проблема с утечкой памяти в моем коде решена
у 1С фича, на освобождение памяти влияет то, как получен Объект тем таких на мисте достаточно |
|||
20
ОбычныйЧеловек
17.09.11
✎
16:47
|
(18) утечки памяти в твоем коде быть не должно.....посмотри что в модуле документа написано (скорее всего проблема там)
|
|||
21
zladenuw
17.09.11
✎
16:54
|
а таблица документов, в ней сколько элементов ? я выгрузку КД с 7.7 загонял в 1,5 гб при выгрузке 200 000 элементов в хмл. когда еще выгружалось.
|
|||
22
Air777
17.09.11
✎
16:58
|
(19) Напиши объем занимаемой виртуальной памяти процессом 1cv8.exe в диспетчере на вечер и на утро после работы твоей обработки поглядим.
(21) Где ты видишь в (10) обращение к модулю документа???? Сейчас для своего успокоения сделаю пустую тестовую базу и попытаюсь воспроизвести проблему. |
|||
23
Air777
17.09.11
✎
16:58
|
(20) Где ты видишь в (10) обращение к модулю документа????
|
|||
24
Jolly Roger
17.09.11
✎
17:08
|
(23) дык вот же:
Объект=Выборка.ПолучитьОбъект(); |
|||
25
zladenuw
17.09.11
✎
17:19
|
(24) то да но почему тогда не идет освобождения памяти если Объект=Ссылка.ПолучитьОбъект();
Объект=Неопределено; Или даже при таком присвоение, выделенная память для объекта остается такой же. |
|||
26
trambalda
17.09.11
✎
17:20
|
Не очень понятно, почему выборка делается не запросом.
|
|||
27
Air777
17.09.11
✎
17:24
|
(26) это сути не меняет. Я пробовал обоими способами. Тут приведен пример без запроса для упрощения
|
|||
28
zladenuw
17.09.11
✎
17:26
|
Слушай может глупо но попробовать так
Процедура КнопкаВыполнитьНажатие(Кнопка) Выборка=Документы.Реализация.Выбрать(Дата("20110801"),); Пока Выборка.Следующий() Цикл Объект=Неопределено; Сообщить(Выборка.Ссылка.Номер); Объект=Выборка.ПолучитьОбъект(); КонецЦикла; Выборка=Неопределено; КонецПроцедуры |
|||
29
Air777
17.09.11
✎
17:29
|
Итак отчитываюсь.
Считаю проблема имеет место быть. Здесь лежит тестовая база http://files.mail.ru/3MVBPS В ней 8тыс не проведенных документов и обработка из (10) Вот результаты тестирования: По объем памяти/виртуальной памяти в МБ 0.Запуск базы 42.5/25 1.Первый запуск обработки "Выполнить" 60.1/40.1 2.Второй запуск 60.9/40.7 3. 61.5/41.3 4. 62.2/42.8 5. 62.8/43.5 ПОЖАЛУЙСТО ПРОВЕРЬТЕ ВОСПРОИЗВОДИМОСТЬ РЕЗУЛЬТАТА Судя по всему нужно обращаться в саппорт 1с с багрепортом. |
|||
30
Fragster
гуру
17.09.11
✎
17:29
|
я поборол итератором в обработке ожидания
|
|||
31
Air777
17.09.11
✎
17:32
|
(28) результат не изменило
(30) по подробнее пожалуйсто |
|||
32
ОбычныйЧеловек
17.09.11
✎
18:41
|
(29) ты не слушаешь...проверь модули документов (утечка именно там) а не твоем вложенном коде.
|
|||
33
Air777
17.09.11
✎
18:58
|
(32) Как нах код????
ГЛАЗА ОТКРОЙ (29) тестовая база с пустыми НЕ ПРОВЕДЕННЫМИ документами С ПУСТЫМ модулем проведения. Результат тот же! О чем ты мне толкуешь? |
|||
34
ОбычныйЧеловек
17.09.11
✎
19:16
|
(33) в (29) ни слова не было о том, что доки с пустым модулем объекта... убери "сообщить" и посмотри как будет "расти" память.
|
|||
35
Air777
17.09.11
✎
19:27
|
(34) безтолку
|
|||
36
ОбычныйЧеловек
17.09.11
✎
19:36
|
(35) вот не поленился, скачал базу (даже 1Ску поставил) - доков 14тыс. создал (убрал сообщение) - память не растет.
|
|||
37
Air777
17.09.11
✎
19:57
|
(36) А ведь ты прав!
Наконец то я понял в чем дело и где утечка. Процедура КнопкаВыполнитьНажатие(Кнопка) Выборка=Документы.Реализация.Выбрать(Дата("20110801"),); Пока Выборка.Следующий() Цикл Объект=Выборка.ПолучитьОбъект(); Сообщить(Объект.Номер); Объект=Неопределено; КонецЦикла; Выборка=Неопределено; КонецПроцедуры Вот так утечки нет!!!!!!!!!!!!!!!! Дело как раз в том что я напрямую читал номер дока из ссылки. Очевидно именно в этот момент тянется все содержимое дока в память, а так как указателя на загружаемый объект нет то он и остается висеть в памяти ибо явно не обнуляется. Офигеть |
|||
38
Air777
18.09.11
✎
02:03
|
Какая то мистика.
Процедура КнопкаВыполнитьНажатие(Кнопка) ТекстЗапроса=" |ВЫБРАТЬ |Ссылка |Из |Документ.Реализация |ГДЕ Дата>=&Дата"; Запрос=Новый Запрос; Запрос.Текст=ТекстЗапроса; Запрос.Параметры.Вставить("Дата",Дата("20110801")); ТаблицаЗапроса=Запрос.Выполнить().Выгрузить(); Для Каждого Выборка Из ТаблицаЗапроса Цикл Объект=Выборка.Ссылка.Получитьобъект(); Объект=Неопределено; КонецЦикла; ТаблицаЗапроса=Неопределено; КонецПроцедуры И снова утечки :( |
|||
39
H A D G E H O G s
18.09.11
✎
02:19
|
Добавь
Объект.Записать(РежимЗаписиДокумента.Запись); И почитай про объектный кэш. Читай Габца. Будь мужиком, блеать! |
|||
40
H A D G E H O G s
18.09.11
✎
02:20
|
||||
41
H A D G E H O G s
18.09.11
✎
02:20
|
p.s. Можешь покурить 20 минут, память сама уйдет.
|
|||
42
Air777
18.09.11
✎
03:19
|
Уже час жду 123Мб отожрала и не отдает зараза
|
|||
43
H A D G E H O G s
18.09.11
✎
07:50
|
(42) Отдаст, когда понадобиться.
(39) помогло? |
|||
44
andrewks
18.09.11
✎
09:27
|
имхо, чел борется с ветряными мельницами, то бишь с виндовозным менеджером памяти. не?
|
|||
45
H A D G E H O G s
18.09.11
✎
12:01
|
(44) Не.
|
|||
46
H A D G E H O G s
18.09.11
✎
12:02
|
ПолучитьОбъект() кэширует объект в память. И хранит его.
Даже если контекст освобождается. 20 минут. или пока _Version не изменится. (при записи). Как и Ссылка.<ИмяРеквизита> |
|||
47
Air777
18.09.11
✎
13:19
|
Память высвободилась но где то далеко через час.
Объект.Записать(); а также Ссылка.<ИмяРевизита> действительно сути не меняет! Меня вот это больше всего и поражает - кэш хранится даже при освобождении контекста. Это как то очень странно. Выходит нет ни одной команды чтобы его принудительно очистить. |
|||
48
H A D G E H O G s
18.09.11
✎
14:57
|
Пилятъ.
Это элементарно, Ватсон Не использовать ПолучитьОбъект()!!! |
|||
49
H A D G E H O G s
18.09.11
✎
14:59
|
Без метода Записать().
Действительно, без метода Записать() он на 99,9% случаев не нужен. 0.01% идет на случай XML/XDTO-сериализации, но не суть. Также не юзать ВЫБОРКА ССЫЛКА.<Реквизит> а - запросы! Запросы - не кэшируются (платформой). |
|||
50
H A D G E H O G s
18.09.11
✎
15:00
|
Да, кстати, я не вполне уверен про кэширование
Справочники.СправочникМенеджер.Выборка(,,,,) Чего не знаю -того не знаю. Ставлю под сомнение ВЫБОРКУ. В профайлер не пойду. Лень. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |