Comments 53
Ваш тест производительности опровергает ваши же утверждения о медлительности DOM и SimpleXML по сравнению с XMLReader. И еще бы не плохо показать объем используемой памяти.
какими средствами лучше разбирать объёмный XML
Во первых надо отказаться от формата и переходить на json в любом случае.
Во вторых получать ленту со стороны сервера уже обработанную, по параметрам.
?part=snippet,contentDetails&maxResults=15&order=date
К сожалению наши поставщики прайс-листов не хотят переходить на параметры и отдают нам XML от 500 до 1500 Mb.
В принципе даже simplexml_load_file можете разбить на блоки, как вот товарищ пишет, он через curl/
Но вот как обрабатывает ошибки json.
Есть же какие то программы, которые конвертируют файл на стороне клиента, только конвертация уменьшит его размер на треть.
Но вот как обрабатывает ошибки json.
Есть же какие то программы, которые конвертируют файл на стороне клиента, только конвертация уменьшит его размер на треть.
$json = curl_exec($ch);
if ($json !== false) {
//решаем проблему ошибок
$json = preg_replace("#(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|([\s\t]//.*)|(^//.*)#", '', $json);
setlocale(LC_ALL, 'ru_RU.utf8');
Header("Content-Type: text/html;charset=UTF-8");
curl_close($ch);
$json = json_decode($json, true) ;
Не так давно пришлось изменять целый модуль после старого программиста, именно из-за его идеи разбивать файл на кучу новых по 30 Mb и разбирать всё это дело через simplexml. Такой утечки памяти добился он что сервер не мог выдержать 100 человек онлайн.
Можно парсить на сущности (теги), используя XMLReader, а затем эту сущность разбирать уже через DomDocument. Таким образом, памяти будет кушать не много, а DomDocument куда более приятен и расширяем, хотя, конечно, по скорости будет чуть медленнее.
А вообще, такие парсеры лучше писать на более шустрых комилируемых языках, к примеру go. Там это в разы будет быстрее работать и можно использовать конкурентные вычисления, писать порциями напрямую в базу. Вы удивитесь насколько это будет шустрее работать и памяти жрать будет в разы меньше
А вообще, такие парсеры лучше писать на более шустрых комилируемых языках, к примеру go. Там это в разы будет быстрее работать и можно использовать конкурентные вычисления, писать порциями напрямую в базу. Вы удивитесь насколько это будет шустрее работать и памяти жрать будет в разы меньше
Ну так я и пишу, в принципе, если очень надо. XMLлом собаку уже съел, искренне не понимаю, кто наминусовал за «Во первых надо отказаться от формата и переходить на json в любом случае.».
Какие то странные кадры пошли в хабрахабре.
curl тут прописал, ибо раз 5 спрашивали в тостере как сделать чтобы кодировка была русская и ошибок не было. Им удобно смотреть и разбирать.
Какие то странные кадры пошли в хабрахабре.
curl тут прописал, ибо раз 5 спрашивали в тостере как сделать чтобы кодировка была русская и ошибок не было. Им удобно смотреть и разбирать.
UFO just landed and posted this here
А как можно обработать большой json (к примеру > 100 мб)? Если вот нужно, и никак иначе? Буду признателен за ответ
В java как-то помнится тупо использовал gson.
использовать streaming json parser
Например: https://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/
Например: https://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/
Если JSON вида
[{}, {}, {}, ...]
или похожий, где структура несложная, но есть большой кусок, который надо обрабатывать потоком, можно сделать так. Читаем посимвольно с учетом вложенности скобок, то есть определяем ситуации «начало массива», «конец массива», «начало объекта», «конец объекта». Задаем уровень вложенности или ключ, которые определяют одну единицу данных. Читаем текст для этой единицы в буфер, буфер передаем в json_decode(). Делаем обработку результата, читаем дальше.Помимо времени выполнения следовало бы замерить использованную память.
У меня тоже есть поставщики фидов по 2-4 gb на xml
Мне пришлось написать безумные вещь для этой задачи.
— Открываю файл и читаю его построчно, пропуская открытие и закрытие, беру около 300 000 строк
— При помощи CURL рассылаю строки на эту же машину + на удаленные машины (24 запроса = 300 000/24)
— Все 24 запроса конвертируют XML в key/value массив
— Система собирает с каждого curl один массив
И так по кругу пока не кончится файл
Из сложного — надо правильно открывать и закрывать xml, чтобы он был валидный.
PS.
24 — это не сервера, это запросы, сервернов 4 по 6 (6 ядрен * на 4 офисные машины)
Проверьте htop, ваш php для этой задачи берет скорее всего только 1 ядро, заставить брать все ядра можно мультизапросами.
Мне пришлось написать безумные вещь для этой задачи.
— Открываю файл и читаю его построчно, пропуская открытие и закрытие, беру около 300 000 строк
— При помощи CURL рассылаю строки на эту же машину + на удаленные машины (24 запроса = 300 000/24)
— Все 24 запроса конвертируют XML в key/value массив
— Система собирает с каждого curl один массив
И так по кругу пока не кончится файл
Из сложного — надо правильно открывать и закрывать xml, чтобы он был валидный.
PS.
24 — это не сервера, это запросы, сервернов 4 по 6 (6 ядрен * на 4 офисные машины)
Проверьте htop, ваш php для этой задачи берет скорее всего только 1 ядро, заставить брать все ядра можно мультизапросами.
Уточняю
— Все 24 запрсоа не только конвертируют XML -> В массив, естественно они сначала конвертируют строки в XML объект. Но так как по XML объект ходить сложно (особенно, когда структура постоянно разная), то я написал функцию конвертации всех параметрво и аттрибутов в key/value массив, который возращается как json
— 24, 300 000 — все эти цифры условные, постоянно перенастраиваются и тд
— Все 24 запрсоа не только конвертируют XML -> В массив, естественно они сначала конвертируют строки в XML объект. Но так как по XML объект ходить сложно (особенно, когда структура постоянно разная), то я написал функцию конвертации всех параметрво и аттрибутов в key/value массив, который возращается как json
— 24, 300 000 — все эти цифры условные, постоянно перенастраиваются и тд
Почитайте мой верхний комментарий.
Из-за таких способов происходит дикая утечка памяти, т.к. вы грузите по 300 000 строк, в то время когда воспользовавшись XMLReader или xml_parser вы будете тратить максимум 1 мегабайт памяти.
P.S. на разбор файла в 1.5 Gb уходит 7 Mb памяти и около 1.5 часа. Это учитывая что кроме разбора файла идёт множество mysql запросов
Из-за таких способов происходит дикая утечка памяти, т.к. вы грузите по 300 000 строк, в то время когда воспользовавшись XMLReader или xml_parser вы будете тратить максимум 1 мегабайт памяти.
P.S. на разбор файла в 1.5 Gb уходит 7 Mb памяти и около 1.5 часа. Это учитывая что кроме разбора файла идёт множество mysql запросов
За что минусуют не могу понять, у меня на разбор уходет от 5 до 15 минут на 7gb xml данных, а у вас 1.5 часа на 1.5
Дикая утечка памяти? Авто же жаловался на скорость, зачем мне экономить память, и это не утечка, а использование. Моя задача скорость и я разбил файл на 300 000 кусков и разослал на обработку 6 серверам всем их ядрам под 100%.
Зачем это делать на сервере с онлайн пользователями — я не понимаю )
XMLReader или xml_parser — я жду их выполнения, что мне толку от их потребления памяти, памяти в избытке, а 300 000 строк по кругу не позволяют ей выйти из того объема, который меня устраивает. Если их же вызвать 24 раза одновременно — будет в 24 раза быстрее, а 300 000/24 — парсер не каждую строчку конвертирует, а все строчки как 1 файл на ядре.
Дикая утечка памяти? Авто же жаловался на скорость, зачем мне экономить память, и это не утечка, а использование. Моя задача скорость и я разбил файл на 300 000 кусков и разослал на обработку 6 серверам всем их ядрам под 100%.
Зачем это делать на сервере с онлайн пользователями — я не понимаю )
XMLReader или xml_parser — я жду их выполнения, что мне толку от их потребления памяти, памяти в избытке, а 300 000 строк по кругу не позволяют ей выйти из того объема, который меня устраивает. Если их же вызвать 24 раза одновременно — будет в 24 раза быстрее, а 300 000/24 — парсер не каждую строчку конвертирует, а все строчки как 1 файл на ядре.
А завтра поменяют разбиение XML-файла на строки и все у вас упадет.
Нет, я не конвертирую строки, я на 1 ядре объединяю их и делаю из них валидный xml, потому не важно как именно разбит файл, идея считывать группу строк, а не весь файл целиком.
Все упадет если файл будет 1 строковый. Ну под это тоже можно написать альтернативу, но по задаче не требуется.
Все упадет если файл будет 1 строковый. Ну под это тоже можно написать альтернативу, но по задаче не требуется.
А как вы будете разбивать файл вот такого формата?
<root><item>
<name>Item 1</name>
</item><item>
<name>Item 2</name>
</item><item>
<name>Item 3</name>
</item><item>
<name>Item 4</name>
</item><item>
<name>Item 5</name>
</item></root>
По строкам, а потом допишу в разрыве xml, чтобы превратить в валидный, чтобы не потерять данные, следующий цикл начнется на пару строк выше разрыва, есть вероятность повтороного попадания данных (дубли), но они пропускаются при импорте
Нужно просто очистить хвост, чтобы в конце остался только закрывающийся тег
Нужно просто очистить хвост, чтобы в конце остался только закрывающийся тег
А завтра поменяют разбиение XML-файла на строки и все у вас упадет.
Вы это уже говорили, я не знаю как бы вам внятно объяснить. Есть открывающие и закрывающие теги, какая разница что там со строками и где что лежит, после получения данных для одного ядра строки соединяются и проверяются на валидность, все обрывистые куски отсеиваются и закрываются те теги, которые нужны, затем передается в xml reader
Это время и память на работу на 1 сервере.
По факту вы делаете кучу лишней работы которая не нужна.
Возможно конкретно в вашем случае это помогло решить какие-то другие задачи, но в целом даже на обработке 300 000 строк я бы использовал xml_reader, а не simplexml
По факту вы делаете кучу лишней работы которая не нужна.
Возможно конкретно в вашем случае это помогло решить какие-то другие задачи, но в целом даже на обработке 300 000 строк я бы использовал xml_reader, а не simplexml
Да, заметил, набежит группа и минусует одновременно. Выбивают в других комментариях, а не по теме срача, кто хоть что то знает, а остаются полит. психи…
Скоро будет жежечка вторая.
Может нервничают от старого железа или перехода на PHP7, где SimpleXML extension были проблемы с установкой.
99% будет ошибка где то в XML, особо при таких гигантских файлах, не пойму как они работают.
Скоро будет жежечка вторая.
Может нервничают от старого железа или перехода на PHP7, где SimpleXML extension были проблемы с установкой.
99% будет ошибка где то в XML, особо при таких гигантских файлах, не пойму как они работают.
Долго. Хотя, если такое время выполнения никому неудобств не доставляет — ну ладно.
Но, в любом случае, насилие БД… Вы при разборе каждого узла делаете запросы? У вас при разборе файла какие запросы превалируют: INSERT или UPDATE? Что, если собирать данные и отправлять их в БД пачками (bulk insert), т.е., вместо 100/200/500 запросов сделать 1? Или возможно, если вы используете innodb и у вас autocommit=1 (по умолчанию), а вы и не знали?
Но, в любом случае, насилие БД… Вы при разборе каждого узла делаете запросы? У вас при разборе файла какие запросы превалируют: INSERT или UPDATE? Что, если собирать данные и отправлять их в БД пачками (bulk insert), т.е., вместо 100/200/500 запросов сделать 1? Или возможно, если вы используете innodb и у вас autocommit=1 (по умолчанию), а вы и не знали?
Была задача распарсить многогиговые XML файлы, делал очень просто, зная структуру XML файла читал построчно, последовательно заполняя и обрабатывая объектную модель. При незнакомом формате, можно в два прохода, на первом строит схему XML, на втором уже зная ее обрабатываем последовательно блоки.
UFO just landed and posted this here
Хм, а у меня xml_parse был быстрее на порядок. :)
Уф… XML в несколько гигов это жесть)) Мне пока максимум доводилось работать с 30-35Мб, использую Simple XML и пару раз DOM за карьеру. Про другие библиотеки не знал, спасибо.
Вы не пробовали использовать xslt преобразования? С их помощью из многомегабайтного XML документа можно вычленить только интересующую вас информацию, а уже её зачитывать в сущности.
По запросу «php stream xml» вроде бы в первых же результатах вылезают ссылки на XMLReader, SAX и другие полезные слова?
(это коммент не к статье, а к товарищам, которые велосипедят)
(это коммент не к статье, а к товарищам, которые велосипедят)
UFO just landed and posted this here
Как насчет использования eXist? Он как раз и создавался для удобства в оперировании большими XML файлами.
Используйте SAX парсер, но не используйте его главную фишку — парсить в потоке?
У вас поэтому такая смешная разница между DOM и SAX.
Этот парсер легко переваривает многогиговые эксельки (любой zip архив с xml), которые офис не в состоянии открыть.
У вас поэтому такая смешная разница между DOM и SAX.
Этот парсер легко переваривает многогиговые эксельки (любой zip архив с xml), которые офис не в состоянии открыть.
https://www.sitepoint.com/functional-programming-phunkie-building-php-json-parser/
— A JSON Parser.
По опыту, большее количество кода это обнаружение и устранение ошибок, вот как работает по новому. См. выше.
— A JSON Parser.
По опыту, большее количество кода это обнаружение и устранение ошибок, вот как работает по новому. См. выше.
Sign up to leave a comment.
Методы работы с «тяжёлыми» XML