- PVSM.RU - https://www.pvsm.ru -
Среднее качество работы парсеров (для семи сайтов)
Предлагаю:
Как гласит народная мудрость: Верить верь, но…
Когда вышел Apache.JMeter 3.0, был ещё в разработке, коллеги и я тестировали его и начали применять в работе. Первым в боевом тестировании применил новую версию Артём zetsigemon [2] для одной из новых услуг pgu.mos.ru [3], где при использовании Apache.JMeter 3.0 качество разбора встроенных ресурсов значительно улучшилось по сравнению с предыдущей версией.
И тут появился вопрос, а каково это качество, как его измерить для разных сайтов, каким оно было и каким стало?
Материалы и результаты исследования отражены в текущей статье.
Тестируются htmlParser-ы для Apache.JMeter 2.13 и Apache.JMeter 3.0.
Парсеры Apache.JMeter 2.13:
Парсесы Apache.JMeter 3.0:
Парсеры разбирают стартовые страницы различных веб-сайтов:
Основой послужили изменения в Apache.JMeter 3.0, см. http://jmeter.apache.org/changes.html [4].
Core improvements
Dependencies refresh
Deprecated Libraries dropped or replaced by up to date ones:
- htmllexer, htmlparser removed
- jdom removed
Удалён парсер htmlparser и более неиспользуемая библиотека jdom.
Protocols and Load Testing improvements
Parallel Downloads is now realistic and scales much better:
- Parsing of CSS imported files (through import [5]) or embedded resources (background, images, …)
Добавлен новый парсер для CSS-файлов, будут извлекаться ссылки на другие CSS-файлы (через import [5]) и ссылки на ресурсы, указанные в CSS-файлах: фоновые изображения, картинки, ...
Incompatible changes
- Since version 3.0, the parser for embedded resources (replaced since 2.10 by Lagarto based implementation) which relied on the htmlparser library (HtmlParserHTMLParser) has been dropped along with its dependencies.
- The following jars have been removed:
Удалён парсер htmlparser и более неиспользуемые библиотеки htmllexer и jdom.
Improvements
HTTP Samplers and Test Script Recorder
- Bug 59036 [8] — FormCharSetFinder: Use JSoup instead of deprecated HTMLParser
- Bug 59033 [9] — Parallel Download: Rework Parser classes hierarchy to allow plug-in parsers for different mime types
- Bug 59140 [10] — Parallel Download: Add CSS Parsing to extract links from CSS files
Для поиска аттрибута
accept-charset
в тегахform
теперь используется JSoup вместо удалённого HTMLParser [Bug 59036]. Реализован парсер CSS-файлов [Bug 59140] и этот парсер используется по умолчанию [Bug 59033].
Сравнить работу всех доступных парсеров. В частности сравнить между собой парсеры версий 2.13 и 3.0, убедиться, что загрузка встроенных ресурсов стала реалистичнее и лучше.
Этап 1:
Этап 2:
Чтобы точно определить сколько запросов посылается во время открытия страницы сайта из Apache.JMeter все запросы логируются:
Чтобы иметь возможность сгруппировать запросы по версиям Apache.JMeter, парсерам и сайтам, в лог будут записываться дополнительные переменные для каждого запроса:
Кардинальных улучшений полноты разбора html-страниц нет, есть ухудшения.
Существенное отличие — в парсерах для Apache.JMeter 3.0 есть рекурсивная загрузка страницы промо-материалов браузера Яндекс Браузер. Это проявляется при загрузке https://yandex.ru/ [12].
На простых сайтах, таких как jmeter.apache.org, все парсеры работают одинаково. Создавая то же количество подзапросов, которое создаётся браузером. Качество работы парсеров для jmeter.apache.org — идеально, 100%.
Но на таком сайте как mos.ru, парсеры найдут в среднем 22 ссылки на встроенные ресурсы, тогда как полная загрузка страницы с загрузкой всех встроенных ресурсов браузером — 144 запроса. Качество низкое.
Аналогично на сайте habrahabr.ru, парсер Lagardo из Apache.JMeter 3.0 найдёт 55 ссылок, тогда как браузер сделает 117 подзапросов. Качество — 47,01%. Удовлетворительное качество полноты извлечения ссылок на встроенные ресурсы.
Таблица на Google Docs: JMeter.HtmlParser.Compare (верхняя таблица) [13].
[14]
Статистика работы Apache.JMeter в разрезе версий и html-парсеров и её сравнение с работой Google Chrome
Описание столбцов:
Хорошим результатом работы парсеров будет, если подзапросов будет столько же, сколько браузер Google Chrome делает на момент Document Complete, а отличным — на момент Fully Loaded. Мерилом реалистичности работы Apache.JMeter при использовании конкретного парсера будем считать близость количества подзапросов к количеству подзапросов, выполняемых браузером на момент Fully Loaded.
Если исключить результаты тестирования сайта yandex.ru, где:
> java.lang.Exception: Maximum frame/iframe nesting depth exceeded
.
И за мерило качества работы парсеров принять количество подзапросов на момент Fully Loaded, то получим такую таблицу среднего качества работы парсеров.
Таблица на Google Docs: JMeter.HtmlParser.Compare (нижняя таблица) [13].
[15]
Среднее качество работы парсеров (для семи сайтов, без yandex.ru)
Самый точный парсер HTMLParser в Apache.JMeter 2.13. В Apache.JMeter 3.0 парсеры Jsoup и JTidy показали одинаковое качество. Парсер Lagarto отстаёт от лидеров. Полнота парсинга для парсера Lagarto в Apache.JMeter 3.0 снизилась по сравнению с Apache.JMeter 2.13.
Качество работы парсера Lagarto на актуальной версии Apache.JMeter 3.0 составило 32,73%, лишь треть всех подзапросов была послана, две трети нагрузки на статику не было подано.
Таблица на Google Docs: Пропущенные дефолтным парсером Apache.JMeter 3.0 ссылки на habrahabr.ru [16]
Пропущенные Apache.JMeter 3.0 ссылки при разборе habrahabr.ru
Пропущено много рекламных материалов и статистики. И это хорошо.
Выше уже оговаривался, что оценивать буду только количественные характеристики. По числам получается, что качество извлечения ссылок на встроенные ресурсы низкое. Детальный анализ может показать, что именно было пропущено. Может оказаться, что это реклама и контент со сторонних ресурсов, который необязательно грузить в рамках нагрузочного тестирования конкретного сайта.
Все логи доступны по ссылке: https://drive.google.com/drive/folders/0B5nKzHDZ1RIiVkN4dDlFWDR1ZGM [17].
sytekey | webpagetest.org | Raw page data (.csv) | Raw object data (.csv) | HTTP Archive (.har) |
---|---|---|---|---|
github.com | 160819_VF_FM8 [18] | github.com.summary.csv [19] | github.com.details.csv [20] | github.com.har [21] |
google.ru | 160819_C9_FQD [22] | google.ru.summary.csv [23] | google.ru.details.csv [24] | google.ru.har [25] |
habrahabr.ru | 160819_8N_FRB [26] | habrahabr.ru.summary.csv [27] | habrahabr.ru.details.csv [28] | habrahabr.ru.har [29] |
jmeter.apache.org | 160819_CG_FSM [30] | jmeter.apache.org.summary.csv [31] | jmeter.apache.org.details.csv [32] | jmeter.apache.org.har [33] |
linkedin.com | 160819_K2_FY1 [34] | linkedin.com.summary.csv [35] | linkedin.com.details.csv [36] | linkedin.com.har [37] |
mos.ru | 160819_91_G0F [38] | mos.ru.summary.csv [39] | mos.ru.details.csv [40] | mos.ru.har [41] |
stackoverflow.com | 160819_S0_G18 [42] | stackoverflow.com.summary.csv [43] | stackoverflow.com.details.csv [44] | stackoverflow.com.har [45] |
yandex.ru | 160819_MR_G1R [46] | yandex.ru.summary.csv [47] | yandex.ru.details.csv [48] | yandex.ru.har [49] |
Из значений колонок Document Complete и Fully Loaded нужно исклюить один запрос (корневой), чтобы получить количество подзапросов.
Для обработки используются csv-логи, сформированные плагином CsvLogWriter:
Сторонний плагин используется, чтобы в csv-лог попали запросы на embedded-ресурсы.
В результате работы CsvLogWriter формируется лог, в список колонок которого входят:
Аггрегация csv-логов Apache.JMeter выполняется при помощи pandas вот таким кодом на python:
import pandas as pd
import codecs
from os import listdir
import numpy as np
# Настройки - каталог с логами и настройки считывания логов.
dirPath = "D:/project/jmeter.htmlParser.3.0.vs.2.13/logs"
read_csv_param = dict( index_col=['timeStamp'],
low_memory=False,
sep = ";",
na_values=[' ','','null'])
# Получение списка csv-файлов в каталоге с логами.
files = filter(lambda a: '.csv' in a, listdir(dirPath))
# Чтение содержимого всех csv-файлов в DataFrame dfs.
csvfile = dirPath + "/" + files[0]
print(files[0])
dfs = pd.read_csv(csvfile,**read_csv_param)
for csvfile in files[1:]:
print(csvfile)
tempDfs = pd.read_csv(dirPath + "/" + csvfile, **read_csv_param)
dfs = dfs.append(tempDfs)
#dfs.to_excel(dirPath + "/total.xlsx")
# Убрать из выборки все JSR223, по ним статистику строить не надо, оставить только HTTP Request Sampler.
# У JSR223 URL пустой, у HTTP-запросов URL указан.
dfs = dfs[(pd.isnull(dfs.URL) == False)]
# Сводная таблица по количеству подзапросов, сохраняется в report.subrequests.html - основной результат работы.
# Из количества запросов удаляется один запрос, чтобы исключить корневой запрос.
# Цель данного исследования - подсчёт количества подзапросов, поэтому корневой исключается.
pd.pivot_table(dfs,
index=['siteKey', "jmeterVersion", "htmlParser"],
values="URL",
columns=["i"],
aggfunc=lambda url: url.count()-1).to_html(dirPath + "/report.subrequest.count.html")
[50]
Рекурсивная загрузка встроенных ресурсов для актуальной версии Apache.JMeter 3.0 с настройками по умолчанию (html-парсер Lagarto) на сайте yandex.ru
Как видно:
https://yandex.ru/clck/redir/dtype=stred....7004fcb3793e79bb1ac9e&keyno=12
https://yandex.ru/clck/redir/dtype=stred....cd1c46cad58fbfe2f61&keyno=12
В данном случае это картинка внутри ссылки на загрузку Яндекс Браузера:
[51]
Фрагмент html-кода сайта yandex.ru обработка которого добавляет новый шаг рекурсии, ссылки и картинка для скачивания Яндекс Браузера
Картинку парсер находит. JMeter пробует её скачать, в ответ получает html-страницу, там снова ссылка на картинку и другие ссылки. И всё повторяется. Поведение Apache.JMeter корректное.
А в Apache.JMeter 2.13 рекурсия просходит только на парсере HtmlParser, догадки почему не происходит на других:
Гадать не буду. Кажется безвыходная ситуация. Но таких ситуаций не бывает. Всегда есть решение.
Например, можно попробовать в качестве User-Agent указать Яндекс Браузер. Тогда сервер, наверно, не покажет картинку для скачивания браузера, или на запрос картинки будет отвечать картинкой, и рекурсии не будет. Это догадка, не проверял её.
Сейчас в скрипте был указан User-Agent для Google Chrome для синхронности с работой webpagetest.org, и сервер видя не свой браузер, видимо, предлагает ссылку на свой.
URL
— адрес тестируемого сайта, например, https://yandex.ru/ [12];siteKey
— строка по которой будет осуществляться группировка записей в логах, например, yandex.ru;loopCount
— количество итераций теста, используется несколько итераций из-за того, что работа веб-сайтов может быть нестабильной;htmlParser.className
— парсер для извлечения ссылок на встроенные ресурсы;/bin/
Apache.JMeter 3.0, путь к тестовому скрипту jmeter.testfile.jmx, опции запуска теста, а также список htmlParser-ов проверка работы которых выполняется;
/bin/
Apache.JMeter 2.13, путь к тестовому скрипту jmeter.testfile.jmx, опции запуска теста, а также список htmlParser-ов проверка работы которых выполняется;
Тест легко изменить под себя, указать свои сайты и нужное количество итераций. Все настройки задаются в файле test.bat.
CALL jmeter.2.13.bat http://stackoverflow.com/ 5 stackoverflow.com
CALL jmeter.2.13.bat https://habrahabr.ru/ 5 habrahabr.ru
CALL jmeter.2.13.bat https://yandex.ru/ 5 yandex.ru
CALL jmeter.2.13.bat https://www.mos.ru/ 5 mos.ru
CALL jmeter.2.13.bat http://jmeter.apache.org/ 5 jmeter.apache.org
CALL jmeter.2.13.bat https://www.google.ru/ 5 google.ru
CALL jmeter.2.13.bat https://www.linkedin.com/ 5 linkedin.com
CALL jmeter.2.13.bat https://github.com/ 5 github.com
CALL jmeter.3.0.bat http://stackoverflow.com/ 5 stackoverflow.com
CALL jmeter.3.0.bat https://habrahabr.ru/ 5 habrahabr.ru
CALL jmeter.3.0.bat https://yandex.ru/ 5 yandex.ru
CALL jmeter.3.0.bat https://www.mos.ru/ 5 mos.ru
CALL jmeter.3.0.bat http://jmeter.apache.org/ 5 jmeter.apache.org
CALL jmeter.3.0.bat https://www.google.ru/ 5 google.ru
CALL jmeter.3.0.bat https://www.linkedin.com/ 5 linkedin.com
CALL jmeter.3.0.bat https://github.com/ 5 github.com
Далее результаты можно вставлять с Excel-файл с настроенными формулами и получать наглядную таблицу результатов.
Можно попробовать доработать парсеры, и по похожей методике отслеживать улучшение качества разбора embedded-ресурсов.
Особой практической ценности в статье нет. Но некоторые полезные выводы сделать можно:
Автор: polarnik
Источник [55]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/177748
Ссылки в тексте:
[1] CsvLogWriter: https://habrahabr.ru/post/308098/
[2] zetsigemon: https://habrahabr.ru/users/zetsigemon/
[3] pgu.mos.ru: https://pgu.mos.ru
[4] http://jmeter.apache.org/changes.html: http://jmeter.apache.org/changes.html
[5] import: https://habrahabr.ru/users/import/
[6] Bug 59037: http://bz.apache.org/bugzilla/show_bug.cgi?id=59037
[7] Bug 59156: http://bz.apache.org/bugzilla/show_bug.cgi?id=59156
[8] Bug 59036: http://bz.apache.org/bugzilla/show_bug.cgi?id=59036
[9] Bug 59033: http://bz.apache.org/bugzilla/show_bug.cgi?id=59033
[10] Bug 59140: http://bz.apache.org/bugzilla/show_bug.cgi?id=59140
[11] https://github.com/pflb/Jmeter.Plugin.CsvLogWriter: https://github.com/pflb/Jmeter.Plugin.CsvLogWriter
[12] https://yandex.ru/: https://yandex.ru/
[13] JMeter.HtmlParser.Compare (верхняя таблица): https://docs.google.com/spreadsheets/d/16l32BFuUdrJmexTgF155HMAGW7EBaBT-rRjuuLc524c/edit?usp=sharing
[14] Image: https://habrastorage.org/files/e83/ca3/df8/e83ca3df89d44bbaa3b47f7e87a77938.PNG
[15] Image: https://habrastorage.org/files/475/1fb/276/4751fb2762834a49a6cbbdba0917f74f.PNG
[16] Пропущенные дефолтным парсером Apache.JMeter 3.0 ссылки на habrahabr.ru: https://docs.google.com/spreadsheets/d/1FqgnkRm4gYrWUN9bBCEPvVo0mdi5lQl_a3mv1wY7tko/edit?usp=sharing
[17] https://drive.google.com/drive/folders/0B5nKzHDZ1RIiVkN4dDlFWDR1ZGM: https://drive.google.com/drive/folders/0B5nKzHDZ1RIiVkN4dDlFWDR1ZGM
[18] 160819_VF_FM8: https://www.webpagetest.org/result/160819_VF_FM8/
[19] github.com.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiblRnUzNUVFM3SUk
[20] github.com.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIieGFaaWFXTU9MWlE
[21] github.com.har: https://drive.google.com/open?id=0B5nKzHDZ1RIidGNQRzJYUXprVzQ
[22] 160819_C9_FQD: https://www.webpagetest.org/result/160819_C9_FQD/
[23] google.ru.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiczE1OVdCaUs5Mkk
[24] google.ru.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiTUNjRk1mOHJIMEk
[25] google.ru.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiYm9EejNNdHBUWnM
[26] 160819_8N_FRB: https://www.webpagetest.org/result/160819_8N_FRB/
[27] habrahabr.ru.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiM2FsMnVLLTMwb2M
[28] habrahabr.ru.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiaFZjZ2paTlUzaUE
[29] habrahabr.ru.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiMG1wZkVub0NRUlU
[30] 160819_CG_FSM: https://www.webpagetest.org/result/160819_CG_FSM/
[31] jmeter.apache.org.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiVzlua0tlTnNXd28
[32] jmeter.apache.org.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIieGk0TjVvZlJVd1U
[33] jmeter.apache.org.har: https://drive.google.com/open?id=0B5nKzHDZ1RIieWdLSGFOeEdZMEE
[34] 160819_K2_FY1: https://www.webpagetest.org/result/160819_K2_FY1/
[35] linkedin.com.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiV19IMjhCUThhTVE
[36] linkedin.com.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiUmdHcWxTc1hGcVk
[37] linkedin.com.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiWHVfRU1zNE84ODg
[38] 160819_91_G0F: https://www.webpagetest.org/result/160819_91_G0F/
[39] mos.ru.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIibFJqU0hzX1IxbmM
[40] mos.ru.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIibzRGNWVXNVRoQW8
[41] mos.ru.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiSUczcXFSXzMzb0E
[42] 160819_S0_G18: https://www.webpagetest.org/result/160819_S0_G18/
[43] stackoverflow.com.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIidlFMbXRObkFyVzA
[44] stackoverflow.com.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiYm0wSUV4YWZzWEk
[45] stackoverflow.com.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiWW1nck4tU0tvb2c
[46] 160819_MR_G1R: https://www.webpagetest.org/result/160819_MR_G1R/
[47] yandex.ru.summary.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiUW5PSXBWMlU4Skk
[48] yandex.ru.details.csv: https://drive.google.com/open?id=0B5nKzHDZ1RIiWml6R3NNQ0J4bk0
[49] yandex.ru.har: https://drive.google.com/open?id=0B5nKzHDZ1RIiQTNkaWFFN0NhOFU
[50] Image: https://habrastorage.org/files/3b8/6f1/eae/3b86f1eae9fc4863bfd8b79ea2c3f71f.PNG
[51] Image: https://habrastorage.org/files/713/0b7/b24/7130b7b24eef4ac98ce766fc03a8d859.PNG
[52] CsvLogWriter: https://github.com/pflb/Jmeter.Plugin.CsvLogWriter/releases
[53] Sanchez92: https://habrahabr.ru/users/sanchez92/
[54] https://github.com/pflb/jmeter.htmlParser.3.0.vs.2.13: https://github.com/pflb/jmeter.htmlParser.3.0.vs.2.13
[55] Источник: https://habrahabr.ru/post/308254/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.