Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Скрипт не может корректно обработать большой объём входного html. #1

Open
KhArtNJava opened this issue Apr 3, 2012 · 7 comments

Comments

@KhArtNJava
Copy link

Привет.
Пытаюсь распарсить
http://ihtik.lib.ru/2011.07_ihtik_hudlit-ru/
Нужно выбрать все имена файлов.
Если делаю:
$elements = $saw->get('table[class=dirlistertable] tr')->toArray();
то падает с ошибкой
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 64 bytes) in /home/u1326/domains/khartn.name/public_html/dev/modules/nokogiri.php on line 217
.
Если же пытаюсь выполнить
$elements = $saw->get('table[class=dirlistertable] tr td:first-child')->toArray();
то падает в тайм-аут.

В первом варианте, когда не падает в тайм-аут, может стоило бы сделать вывод массива в файл, например, сериализовав его?
Тогда можно было бы избежать переполнения.
Или как-то разбивать данные, сбрасывая их на файловую подсистему.
Если есть ещё какие-то идеи - готов к обсуждению.

@olamedia
Copy link
Owner

olamedia commented Apr 8, 2012

потестирую сейчас

@olamedia
Copy link
Owner

olamedia commented Apr 8, 2012

Итак, 6Мб исходный документ, 28 Мб после get('tr'), 102 Мб после toArray().
В итоге рекомендую отказаться от ->toArray(), а вызвать ->toDom() и работать напрямую с ним, раз не предвидится больше памяти (по времени разница в одну секунду на разбор этих 6 Мб - 41 и 42 секунды)

@olamedia
Copy link
Owner

olamedia commented Apr 8, 2012

Уточню почему:

  1. сам массив занимает дополнительное место.
  2. в массиве используются текстовые ключи для удобства (class, #text) доступа к тексту и атрибутам по их названию. так что массив занимает на порядок больше места.
  3. В данном случае получалось 75 тысяч элементов, на каждый из них массив с текстом и аттрибутами. В итоге около 60 Мб + 30Мб осталось в DOM в самой пиле.

Выбор стоит либо добавить памяти либо общаться напрямую с DOM

@olamedia
Copy link
Owner

olamedia commented Apr 8, 2012

По таймауту действительно странно.
Сам xpath формируется вроде как верно: //table[@class='dirlistertable']//tr//td[1]
Если написать table[class=dirlistertable]>tbody>tr>td:first-child, то отрабатывает за те же 40 секунд с xpath //table[@class='dirlistertable']/tbody/tr/td[1] и 36 Мб

@KhArtNJava
Copy link
Author

А на хостинге ограничение - 30 сек. :).
Вобщем, решил не заморачиваться и сделал всё на регулярках.
Отлетает за 1-2 секунды теперь.
P.S. Отказался от nokogiri - проект ещё слишком сырой и работает медленно.
Желаю удачи в допиливании библиотеки :).

@olamedia
Copy link
Owner

set_time_limit() не катит?
P.S. скорость работы nokogiri сравнима со скоростью встроенных расширений DOM/libxml. Если говорите, что работает медленно, сравнивайте с аналогами.

strpos работает еще быстрее, может не стоило заморачиваться с регулярками? )

@KhArtNJava
Copy link
Author

Touché ))).
set_time_limit() не катит... Отключён на хостинге.
А если сравнивать с другими аналогами, то да, nokogiri заметно быстрее парсит данные.
Но в любом случае стоит ещё поработать над nokogiri в плане оптимизации производительности...
Так, чтобы nokogiri могла без проблем обрабатывать такие вот файлы, как описано в данной заявке.

olamedia pushed a commit that referenced this issue Sep 9, 2020
@olamedia olamedia added the v1.0 label Sep 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants