Rust Reqwest в 10 раз медленнее, чем Postman и Firefox

Я тестировал производительность запроса в Rust, но почему-то выполнение response.text().await занимает добрых 1-3 секунды. Я тестировал ту же самую страницу с почтальоном и Firefox, и это занимает всего 100-300 мс. Я пробовал несколько раз, и каждый раз Postman и Firefox работали быстрее.

Я также пробовал использовать Hyper с .aggregate() и пробовал использовать .bytes() и .chunk() reqwest, и все они такие же медленные. Интересно то, что .send().await занимает обычные 100-300 мс, как и должно быть. Вызов .content_length() также вполне эффективен. Я также пробовал использовать Javascript fetch() и вызывать await response.json(), но это наверняка быстрее.

Кроме того, это не имеет никакого отношения к сборке выпуска, поскольку запуск exe-файла вручную выполняется так же медленно. Rust и reqwest также полностью обновлены.

Вот код:

use std::time::Instant;

#[tokio::main]
async fn main() {
    let client = reqwest::Client::new();

    let response = client
        .get("https://registry.npmjs.org/react")
        .send()
        .await
        .unwrap();

    let now = Instant::now();
    let data = response.text().await;
    let elapsed = now.elapsed();

    println!("{}ms", elapsed.as_millis());
}

Использование reqwest::blocking также не имеет значения:

use std::time::Instant;

fn main() {
    let now = Instant::now();
    let data = reqwest::blocking::get("https://registry.npmjs.org/react")
        .unwrap()
        .text()
        .unwrap();
    let elapsed = now.elapsed();

    println!("{}ms", elapsed.as_millis());
}

Время, необходимое для запроса, уменьшается, если я запрашиваю конечную точку с меньшим количеством данных. Например https://registry.npmjs.org/react/is-even занимает 300 мс с запросом, но все равно 70 мс с Postman.

Есть идеи, что является причиной этого?

Я не умею воспроизводить. И около 350 мс для /react, и около 120 мс для /is-even с моей машины. Мой внешний HTTP-клиент иногда работает немного быстрее (до 100 мс быстрее), но это было только тогда, когда он повторно использовал соединение и, таким образом, пропускал стоимость установления связи TLS. Но даже это не объясняет 3 секунды в вашем случае. Вы уверены, что ваш код Rust работает в тех же сетевых условиях, что и Firefox и Postman (т. е. VPN, прокси-сервер или дополнительный брандмауэр)?

kmdreko 17.09.2023 17:40

Да, я уверен, просто чтобы убедиться, что я также отключил VPN в настройках Windows и попробовал еще раз. Что для меня действительно странно, так это то, что использование Curl обеспечивает очень похожее время загрузки, однако Firefox делает это в 5 раз быстрее. Я убедился, что он не кешируется, запросив новый пакет, но Firefox, безусловно, быстрее. Наверное, мне здесь не хватает чего-то простого, хаха

conaticus 17.09.2023 18:07

Да, и еще одно замечание: я попробовал то же самое в Fedora вместо Windows, и это заняло столько же времени.

conaticus 17.09.2023 18:11

Firefox передает accept-encoding: gzip, deflate, br, на что Registry.npmjs.org отвечает данными в формате gzip (content-encoding: gzip), что может значительно уменьшить размер полезной нагрузки. При этом время запроса на моей машине сокращается с 350 мс до ~ 240 мс, а затем снова, если соединение TLS используется повторно, общее время может снизиться до ~ 120 мс. Кстати, у reqwest есть функция "gzip", которая проанализирует его за вас.

kmdreko 17.09.2023 18:28

Очаровательный! На самом деле я просто читал документацию реестра и там упоминался заголовок Accept: application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*. Похоже, это делает то же самое и ускоряет поиск в 2 раза. Учитывая, что у вас, вероятно, более быстрый Интернет, чем у меня, и вы можете быть ближе к серверу распространения, это имеет смысл! Я также нашел способ использовать {registry}/{package}/{version} вместо этого, чтобы получить значительно меньшие размеры тела. Спасибо за помощь!

conaticus 17.09.2023 18:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На самом деле существует множество факторов, которые приводят к такому неожиданному результату. Вот наши выводы.

  • Вы можете использовать заголовок application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */* (согласно документам реестра NPM), чтобы значительно уменьшить размер полезной нагрузки и выполнить запрос быстрее. Вы также можете сделать Content-Encoding: gzip, но это немного медленнее.
  • Вероятно, с заголовками Firefox связано некоторое кэширование на стороне сервера, и, возможно, именно поэтому он работает так быстро, даже когда кеширование браузера отключено. При очистке кеша и файлов cookie достигается ожидаемое время отклика.
  • Возможно, поскольку я живу в отдаленном районе, ближайший распределительный центр находится довольно далеко, поэтому время моего ответа немного замедляется.
  • Использование GET·/{package}/{version} вместо GET·/{package} в дополнение к заголовку — гораздо лучшее решение, если это возможно в вашем приложении.

Обратите внимание, что эти результаты не являются на 100% достоверными, а являются предположениями. Я обновлю этот ответ, если найду дополнительную информацию. Приятного кодирования!

Другие вопросы по теме