В качестве разминки, а, заодно, и интереса, решал проверить какая из трех библиотек: Synapse, Indy или HTTP Client API окажется быстрее при отправке и получении обычного GET. При этом следует отметить, что, отличие от сравнения скорости, например, работы со строками в Delphi, определить какая из трех библиотек для работы с HTTP(s) сложнее. Ведь на скорость работы влияет не только «железо» непосредственно вашего компьютера, но также и множество других факторов, таких как скорость ответа сервера на ваш запрос, скорость вашего соединения и так далее. И, даже, используя одну и ту же библиотеку, выполняя с интервалом в секунду запрос к одному и тому же серверу можно получить совершенно разное время отклика, а значит, что и результаты проверки будут «смазаны». Поэтому оговорюсь:
- Проверка скорости обработки запроса осуществлялась при выполнении запроса одного и того же URL — https://www.google.ru, что позволило исключить из итогового значения счётчика времени время на осуществления редиректов к целевому URL.
- Каждая библиотека тестировалась десять раз и выводилось среднее время выполнения запроса.
- Полученный в результате ответ сервера никак не обрабатывался, то есть — выполнили запрос, получили код статуса 200 и успешно забыли про результат.
- Тест проводился в приложении, написанном в Delphi 10.3 Rio Release 1.
Код для проверки скорости работы Synapse:
for var I := 1 to 10 do begin httpsend := THTTPSend.Create; try t := t.StartNew; httpsend.HTTPMethod('GET', 'https://www.google.ru'); t.Stop; finally FreeAndNil(httpsend); end; StringGrid1.Cells[1, I] := t.ElapsedMilliseconds.ToString; Application.ProcessMessages; Sleep(1000); end;
Код для проверки скорости работы HTTP Client API:
for var I := 1 to 10 do begin t := t.StartNew; NetHTTPClient1.Get('https://www.google.ru'); t.Stop; StringGrid1.Cells[2, I] := t.ElapsedMilliseconds.ToString; Application.ProcessMessages; Sleep(1000); end;
Код для проверки скорости работы Indy:
for var I := 1 to 10 do begin t := t.StartNew; IdHTTP1.Get(Edit1.Text); t.Stop; StringGrid1.Cells[3, I] := t.ElapsedMilliseconds.ToString; Application.ProcessMessages; Sleep(1000); end;
То есть, как видите, проверка скорости везде идентичная — запускаем таймер перед самой отправкой GET и выключаем сразу после выполнения запроса. Все остальные операции — вывод времени в StringGrid, задержка в 1 секунду перед следующим запросом на время таймера никак не влияют. И, надо сказать, что итоговый результат проверки скорости Synapse, HTTP Client API и Indy меня несколько удивил. Вот какие результаты были получены после пятикратной проверки (то есть в общей сложности было сделана серия из 5 тестов по 10 запросов к Гуглу):
Среднее время выполнения запроса, мс:
- Synapse: 320,86
- HTTP Client API: 106,6
- Indy: 112,74
Если посмотреть на диаграмму по всем пяти сериям, то увидим вот такую картину:
То, что HTTP Client API показала лучший результат, меня особенно не удивило по той простой причине, что я не знал, в принципе, чего ждать от этой библиотеки, так как для меня она пока новая и не достаточно изученная. Также не удивился бы и в том случае, если бы эта библиотека показала и самый худший результат.
А вот то, что Synapse при работе в Delphi 10.3 Rio оказалась в три раза медленнее, чем Indy, честно говоря, очень и очень сильно удивило. Всё время как-то считалось, что Synapse будет по-быстрее монструозной Indy, а оно вон как оказалось…
Единственное, в чем Indy действительно сильно проиграла и Synapse и HTTP Client API так это по скорости выполнения самого первого запроса сразу после запуска программы. Здесь результаты оказались следующие:
- Synapse: 529
- HTTP Client API: 443
- Indy: 1645
В остальном Synapse сильно отстал в работе от «родных» библиотек для работы с HTTP. Возможно, что такие плачевные результаты Synapse связаны с тем, что библиотека последние несколько лет практически не обновлялась для Delphi и использует уже устаревшие на данный момент методы работы со строками, но, как говориться, имеем то, что имеем — HTTP Client API на данный момент оказалась быстрее, чем Indy и Synapse.
Обновление
Как справедливо отметили Kazantsev Alexey и Льоха ШЕЛС в комментариях, причина плохих результатов Synapse связана с некорректным тестом. За это ребятам спасибо. исправил тест Synapse следующим образом:
httpsend := THTTPSend.Create; try httpsend.Protocol := '1.1'; httpsend.KeepAlive := True; for var I := 1 to 10 do begin t := t.StartNew; httpsend.Clear; httpsend.HTTPMethod('GET', Edit1.Text); t.Stop; StringGrid1.Cells[1, I] := t.ElapsedMilliseconds.ToString; Application.ProcessMessages; Sleep(1000); end; finally FreeAndNil(httpsend); end;
Соответственно, изменились и результаты:
Обновление 2
Результаты теста при одинаковых значениях User-Agent:
Размер возвращаемого документа: 11754 – 11760 байт
Книжная полка
Описание Подробно рассматривается библиотека FM, позволяющая создавать полнофункциональное программное обеспечение для операционных систем Windows и OS X, а также для смартфонов и планшетных компьютеров, работающих под управлением Android и iOS
|
||
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
Привет, Влад. Причина провала Synapse кроется в некорректном тесте. 1. Запросы для Indy и HttpClient делаются в рамках одного объекта, что позволяет им использовать постоянное соединение (Connection: keep-alive). Для Synapse на каждый вызов создаётся новый объект, поэтому она такой возможности лишена. 2. Indy и HttpClient по умолчанию используют протокол версии 1.1, тогда как Synapse 1.0, поэтому без дополнительных настроек она не сможет использовать постоянное соединение, даже при условии выполнения запросов в рамках одного объекта. Что нужно сделать для исправления ситуации. 1. Создать объект THTTPSend перед началом тестирования 2. У созданного объекта изменить версию протокола на 1.1 (httObj.Protocol := ‘1.1;’) 3.… Подробнее »
Kazantsev Alexey, привет. Спасибо за совет Алексей. Проверю и в статье обновление сделаю.
UPD: проверил, да, действительно с Keep-Alive среднее время оказалось лучше — 125,50.
Тут ещё момент. Чтобы Synapse работала по https, ей нужно библиотеки из OpenSSL подкладывать.
Kazantsev Alexey, да так и есть — библиотеки рядом с exe были
А ssl_openssl в юнитах был?
Был. Иначе запрос не проходит — возвращает 500 код. Результат с одинаковым User-Agent добавил. Теперь Synapse в лидерах :), а у HTTP Client API какой-то подозрительный рост времени от одной серии к другой…при этом, кроме User-Agent ничего не менялось
Обнаружил ещё один момент. Из-за разного User-Agent, гугловский сервер отдаёт разные страницы. Для Synapse отдаётся документ около 40 KB, для HttpClient около 12 KB. Для корректности теста ещё и User-Agent нужно сделать одинаковым.
Вот! С User-Agent дело всё стало выглядеть совсем по-другому. Самый первый запрос:
Synapse — 422
HTTP Client API — 332
Indy — 1542
А уже дальше картина меняется следующим образом. При одном и том же User-Agent размер страницы 11754 — 11760 байт для всех трех библиотек, время выполнения запроса:
Synapse — 89-99 мс
HTTP Client API — 99-120 мс
Indy — 90 — 118 мс.
Общий итог выложу чуть позже. Спасибо, Алексей, за помощь! :)
Все таки сравнение не совсем корректное в случае с Synapse.
в цикле создается обьект, поток идет блок try, который тоже сжирает ресурсы, потом уничтожение обьекта.
Из-за этого может быть Synapse показал такие медленные результаты.
В остальных двух циклах работа идет с одним и тем же обьектом.
Попробуйте их так же создавать в цикле.
Льоха ШЕЛС, спасибо за отзыв. Проверю