|
Загрузка XML большого обьема | ☑ | ||
---|---|---|---|---|
0
RolandGrey
10.02.15
✎
07:50
|
Имеется необходимость загружать в 1Ску хмл большого объема (от 500 000 строк). Обработка грузит через объект ЧтениеХМЛ. Пробовал писать каждый считанный объект в базу или сразу пачкой (до 1000 за раз) - 1с все равно выжирает всю память и падает.
Что можно предпринять? разбивать файл на куски руками и каждый раз загружать новый кусок в новой сессии не вариант. Пробовал в обработке разбивать файл на куски и закрывать-открывать чтениеХМЛ заново - не помогает. |
|||
1
Cube
10.02.15
✎
07:54
|
(0) В качестве бреда: создай пустую базу, подключись к ней по COM из своей боевой. В COM-базе читай разные куски XML с закрытием/открытием COM-соединения после каждого куска :)
|
|||
2
ShoGUN
10.02.15
✎
07:55
|
(0) Версия платформы 1с какая? Больно странные симптомы, похоже на баг.
|
|||
3
GenV
10.02.15
✎
07:58
|
(0) Определись из-за чего падает - из-за записи большого объема данных или во время чтения из XML. Тогда можно думать дальше.
|
|||
4
Рэйв
10.02.15
✎
07:59
|
может поможет
http://infostart.ru/public/304764/ |
|||
5
RolandGrey
10.02.15
✎
09:25
|
платформа 8.3.5.1383. Смотрел на файловом пока варианте.
Мониторю уровень отжираемой памяти - падает +- при одном объеме. (2) я пробовал писать сразу всю таблицу, пробовал писать кусками по 1000 объектов, пробовал писать сразу по одному. В любом случае память отжирается и все падает, где-то быстрее где-то медленнее. (3) как это определить? (4) как я понял последовательный вызов из основной обработки обработку чтения узла. Попробую, если ничего не поможет |
|||
6
Зеленый Кот
10.02.15
✎
09:29
|
это элементарно!
пишешь обработку на vc++ которая читает xml и толкает в 1С по OLE |
|||
7
ShoGUN
10.02.15
✎
09:31
|
(5) На 8.3.5.1383 есть проблемы как раз с падением при большом потреблении памяти, лично сталкивался, правда, на серверной. Попробуй обновиться, возможно, извращаться не придётся. По крайней мере, это быстро можно сделать.
|
|||
8
Зеленый Кот
10.02.15
✎
09:33
|
(7) +1
|
|||
9
ShoGUN
10.02.15
✎
09:49
|
Во всяком случае, 1000 объектов - это далеко не самый большой объём транзакции, а последовательное чтение потребляет довольно мало памяти. Не вижу объективных причин для способов вроде (1) или (6).
|
|||
10
RolandGrey
10.02.15
✎
09:56
|
(7) спасибо, попробую обновиться и отпишу потом - помогло или нет.
|
|||
11
Зеленый пень
10.02.15
✎
09:57
|
(0) Странно. Что за объекты? ЧтениюXML должен быть фиолетов объем файла, причина скорее всего в другом месте.
|
|||
12
RolandGrey
10.02.15
✎
10:55
|
(11) пока просто справочник номенклатура. Так ЧтениюХМЛ пофиг :) - 1ска отжирает память и система ее убивает
|
|||
13
Лодырь
10.02.15
✎
10:59
|
(12) Вопрос, а если читать и не создавать объекты в 1с - 1ска падает? То есть выяснить причина в созданных объектах или в чтении.
|
|||
14
ShoGUN
10.02.15
✎
11:04
|
(13) В объектах, к гадалке не ходи.
|
|||
15
Лодырь
10.02.15
✎
11:11
|
(14) Ну и у меня такая же мысль. Но тогда проблема немного другая, как создать кучу объектов и не свалится от переполнения. У меня схожая проблема была при выгрузке. Решил разбиением на мелкие порции.
|
|||
16
Dmitrii
гуру
10.02.15
✎
11:11
|
http://its.1c.ru/db/metod8dev#content:3617:hdoc:_top:утечки%20памяти
Утечки памяти В технологическом журнале предусмотрена возможность отслеживания утечек памяти при выполнении заданных участков кода конфигурации. Важным частным случаем контролируемого участка кода конфигурации является процесс. Если в конфигурационном файле технологического журнала контроль утечек памяти задан следующим элементом leaks: <leaks Collect=1> <point Call="client"/> <point Сall="server"/> </leaks> то в технологический журнал будет выведена информация об объектах, которые были созданы, но не были освобождены между началом и окончанием процесса на сервере (<point Сall="server"/>) и на клиенте (<point Call="client"/>). |
|||
17
Dmitrii
гуру
10.02.15
✎
11:14
|
http://its.1c.ru/db/v8std#content:2149184374:hdoc:_top:утечка%20памяти
Следует использовать объекты для последовательной записи и последовательного чтения: ЧтениеXML, ЧтениеТекста, ЗаписьXML, ЗаписьТекста, с помощью которых можно прочитать файл порциями и расходовать память экономно. При использовании механизмов XDTO неправильно зачитывать в память весь XML-файл целиком (ФабрикаXTDO.ПрочитатьXML(ЧтениеXML)). Вместо этого следует зачитывать XML-файл последовательно, с помощью объекта ЧтениеXML, а его отдельные фрагменты (теги) десериализовывать с помощью фабрики XDTO. 4. Другая распространенная причина неэффективное использование памяти - утечки памяти. К утечкам памяти приводит создание циклических ссылок – память выделяется и не освобождается. Например, если есть объекты, внутри которых вложены другие объекты, и где-то в глубине они ссылаются на самый верхний объект. В результате образуется циклическая ссылка. Упрощенный пример циклической ссылки: Данные = Новый Структура; Данные.Вставить("Ключ", Данные); Следует разрывать (очищать) ссылки, когда объект становится не нужен. Например, для примера выше: Данные.Ключ = Неопределено; Для выявления утечек памяти можно применять технологический журнал, включив в файл настройки параметров технологического журнала logcfg.xml элемент <leaks>. |
|||
18
H A D G E H O G s
10.02.15
✎
11:27
|
(0) Обработка - типовая? Если да - то там есть достаточно туповатое кэширование загруженных, без ограничения по "свежести".
|
|||
19
RolandGrey
10.02.15
✎
12:08
|
(18) нетиповая
подсказанные решения смогу опробовать только вечером |
|||
20
Гёдза
10.02.15
✎
12:16
|
В тз грузишь небось, а потом объекты создаешь?
|
|||
21
Андрюха
10.02.15
✎
12:40
|
(0) Покажь код загрузки xml
|
|||
22
RolandGrey
10.02.15
✎
12:56
|
(20) изначально было так. Потом ради эксперимента стал писать кусками по 1000 объектов в тз, потом пообъектно писать начал. Ситуация кардинально не менялась.
(21) телега не моя, я ее дополняю: Попытка // Читаем очередной тэг Пока Чтение.Прочитать() Цикл ф = 1; // При чтении открывающего тэга определяются атрибуты этого тэга. // Также становится известно имя тэга, по которому определяем обрабатываемый объект Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда если найти(Чтение.Имя, "Object") > 0 тогда //новый объект ВсегоСтрок = ВсегоСтрок + 1; КонецЕсли; // В режиме отладки выводим проверочные сообщения Сообщить_("Начало нового тэга"); ЧтениеИмя = Чтение.Имя; ЧтениеУровень = ЧтениеУровень + 1; // Тэг открылся, значит начался новый уровень вложенности ЧтениеКоличествоАтрибутов = Чтение.КоличествоАтрибутов( ); Сообщить_( ЧтениеИмя + " [уровень вложенности " + Строка( ЧтениеУровень ) + "], количество атрибутов " + ЧтениеКоличествоАтрибутов ); // В режиме отладки выводим список атрибутов Если РежимОтладки И ЧтениеКоличествоАтрибутов > 0 Тогда Пока Чтение.ПрочитатьАтрибут() Цикл Сообщить_( "Атрибут - " + Чтение.Имя ); КонецЦикла КонецЕсли; // Тип данных определим для конкретного поля данных или сохраним в нем имя объекта (справочника или документа). ЧтениеТипДанных = ""; // В зависимости от текущего уровня по разному обрабатываем наш тэг Если ЧтениеУровень = 3 Тогда // На третьем уровне идет описание объекта (Справочник или Документ) СтрокаОбъектаДанныхXML = ТЗДанныхXML.Добавить( ); СтруктураЗначенийШапки = Новый Структура; СтруктураЗначенийТЧ = Новый Структура; // Если имя тэга начинается с CatalogObject, то это справочник Если Найти(ЧтениеИмя,"CatalogObject.") > 0 Тогда ЧтениеТипДанных = ЧтениеИмя; // Запоминаем его имя // Если имя тэга начинается с DocumentObject, то это документ ИначеЕсли Найти(ЧтениеИмя,"DocumentObject.")>0 Тогда ЧтениеТипДанных = ЧтениеИмя; // Запоминаем его имя Иначе // Остальное не предусмотрено форматом, поэтому пропускаем КонецЕсли; // Если прочитан правильный тэг (документ или справочник), то добавляем его в строку таблицы сбора данных Если ЧтениеТипДанных <> "" Тогда СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока = ЧтениеТипДанных; КонецЕсли; КонецЕсли; // ЧтениеУровень = 3 // На четвертом уровне поля шапки документа / справочника Если ЧтениеУровень = 4 Тогда // данные шапки только на уровне 4 // Ищем указатель на объект, в который необходимо добавить данные // На третьем уровне в СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока было записано имя справочника или документа СтрокаОбъектаДанныхXMLОбъектXMLТипДанных = НЕОПРЕДЕЛЕНО; // Если это был справочника, то ищем в метаданных описание этого справочника Если Найти(СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока,"CatalogObject.")>0 Тогда // Убираем префикс CatalogObject. СправочникВид = СтрЗаменить( СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока, "CatalogObject.", "" ); Если Метаданные.Справочники.Найти( СправочникВид ) <> НЕОПРЕДЕЛЕНО Тогда СтрокаОбъектаДанныхXMLОбъектXMLТипДанных = Справочники[СправочникВид]; КонецЕсли; // Иначе, это должен быть документ ИначеЕсли Найти(СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока,"DocumentObject.")>0 Тогда ДокументВид = СтрЗаменить(СтрокаОбъектаДанныхXML.ОбъектXMLТипДанныхСтрока,"DocumentObject.",""); Если Метаданные.Документы.Найти( ДокументВид )<>НЕОПРЕДЕЛЕНО Тогда СтрокаОбъектаДанныхXMLОбъектXMLТипДанных = Документы[ ДокументВид ]; КонецЕсли; КонецЕсли; // Если у найденного объекта есть табличная часть, то создаем объект для чтения табличной части Если СтрокаОбъектаДанныхXMLОбъектXMLТипДанных <> НЕОПРЕДЕЛЕНО Тогда Если СтрокаОбъектаДанныхXMLОбъектXMLТипДанных.ПустаяСсылка().Метаданные().ТабличныеЧасти.Найти(ЧтениеИмя) <> НЕОПРЕДЕЛЕНО Тогда Сообщить_("Найдена табличная часть"); ТЗ = Новый ТаблицаЗначений; ИмяТЗ = ЧтениеИмя; КонецЕсли; КонецЕсли; КонецЕсли; // ЧтениеУровень = 4 // Пятый уровень не должен ничего содержать. Он говорит о начале новой строки. // Поэтому добавляем строку в табличную часть Если ЧтениеУровень = 5 Тогда СтрокаТЗ = ТЗ.Добавить(); КонецЕсли; // Начало шестого уровня содержит имя колонки табличной части Если ЧтениеУровень = 6 Тогда Если ТЗ.Колонки.Найти( ЧтениеИмя ) = НЕОПРЕДЕЛЕНО Тогда ТЗ.Колонки.Добавить( ЧтениеИмя ); КонецЕсли; КонецЕсли; // Обработка начала тэга звершена // Обработка значения тэга ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст Тогда // Запоминаем текущее значение тэга. В нашем формате, значения могут иметь только поля данных. Сообщить_("Значение тэга " + Чтение.Значение ); ЧтениеЗначение = СокрЛП(Чтение.Значение); ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда Сообщить_("Тэг завершения"); // Если завершился третий (для нас верхний) уровоень, то просто запоминаем в табле сбора данных список собранных полей Если ЧтениеУровень = 3 Тогда СтрокаОбъектаДанныхXML.ОбъектXMLДанныеШапки = СтруктураЗначенийШапки; СтрокаОбъектаДанныхXML.ОбъектXMLДанныеТЧ = СтруктураЗначенийТЧ; КонецЕсли; // Завершение четвертого уровня, говорит о том что прочитано поле данных шапки или строка табличной части Если ЧтениеУровень = 4 Тогда // Если была прочитана строка табличной части, то запоминаем ее и создаем новую Если ( ТЗ.Количество( ) > 0 ) И ( ИмяТЗ <> "" ) ТОгда СтруктураЗначенийТЧ.Вставить( ИмяТЗ, ТЗ ); ТЗ = Новый ТаблицаЗначений; ИмяТЗ = ""; Иначе // Было прочитано поле данных, добавлем его в шапку Если ЧтениеЗначение <> 0 Тогда СтруктураЗначенийШапки.Вставить(ЧтениеИмя,ЧтениеЗначение); КонецЕсли; КонецЕсли; КонецЕсли; // На пятом уровне ничего не может быть // На шестом уровне могут быть только значения табличной части. Если ЧтениеУровень = 6 Тогда СтрокаТЗ[ ЧтениеИмя ] = ЧтениеЗначение; КонецЕсли; // Тэг закончился, выходим на уровень вверх ЧтениеУровень = ЧтениеУровень - 1; ЧтениеЗначение = 0; если найти(Чтение.Имя, "Object") > 0 тогда //новый объект //если всегоСтрок > 1000 тогда записатьТаблицуЗначений(ТЗДанныхXML); ВывестиПрочитанныеДанные(ТЗДанныхXML); ТЗДанныхXML = Новый ТаблицаЗначений; ТЗДанныхXML.Колонки.Добавить("ОбъектXML"); ТЗДанныхXML.Колонки.Добавить("ОбъектXMLТипДанныхСтрока"); ТЗДанныхXML.Колонки.Добавить("ОбъектXMLДанныеШапки"); ТЗДанныхXML.Колонки.Добавить("ОбъектXMLДанныеТЧ"); //ТЗДанныхXML.Очистить(); // //ТЗДанныхXML.Колонки.Удалить(ТЗДанныхXML.Колонки.Найти("ОбъектXMLТипДанных")); //ТЗДанныхXML.Колонки.Удалить(ТЗДанныхXML.Колонки.Найти("НеЗагружать")); //ТЗДанныхXML.Колонки.Удалить(ТЗДанныхXML.Колонки.Найти("ОбъектНайден")); если всегоСтрок > 1000 тогда всегоСтрок = 0; ВсегоШагов = ВсегоШагов + 1; сообщить("Шаг № " + ВсегоШагов); КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла; // Конец цикла чтения XML файла //если ВсегоСтрок > 0 тогда // // записатьТаблицуЗначений(ТЗДанныхXML); // ВывестиПрочитанныеДанные(ТЗДанныхXML); // //КонецЕсли; Исключение Сообщить( ОписаниеОшибки( ) ); Возврат Результат; КонецПопытки; |
|||
23
sda553
10.02.15
✎
12:59
|
Было уже
v8: Чем работать с большими xml |
|||
24
RolandGrey
10.02.15
✎
13:03
|
(23) с помощью DOM приятнее работать, но большие вещи это дело в принципе не переваривает.
|
|||
25
Fragster
гуру
10.02.15
✎
13:03
|
Чтение.Прочитать();
Пока Чтение.ТипУзла <> ТипУзлаXML.КонецЭлемента Цикл Объект = ФабрикаXDTO.ПрочитатьXML(Чтение); // Тут объект преобразовываешь/записываешь КонецЦикла; а если еще и схема есть, то вообще норм. |
|||
26
Fragster
гуру
10.02.15
✎
13:04
|
иногда надо два раза .Прочитать()
|
|||
27
Fragster
гуру
10.02.15
✎
13:05
|
в зависимости от входного XML.
Хотя объект из 1000000 строк таким образом без промежуточного "проскакивания" прочитывается |
|||
28
RolandGrey
10.02.15
✎
13:15
|
(25) схемы нету
несколько способов уже подсказали, буду пробовать ) |
|||
29
RolandGrey
11.02.15
✎
08:57
|
в-общем причину, кажется, нашел. Но как правильно устранить не совсем понимаю.
Дело в том, что по ходу обработки пишется много сообщений методом Сообщить. И когда завершается чтение файла и переход обратно в форму - они все пытаются вывестись и система обжирается памятью и падает. вопрос - как правильно организовать вывод сообщений? |
|||
30
Лодырь
11.02.15
✎
09:02
|
(29) писать их в лог например. а потом показать лог.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |