powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как ускорить libcurl?
25 сообщений из 31, страница 1 из 2
Как ускорить libcurl?
    #39446542
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Загружаю страницу с помощью curl двумя способами:

libcurl
system("curl")

Код первого способа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
/**
Коллбэк функция для curl
*/
size_t curlClbck( char *ptr, size_t size, size_t nmemb, std::string* data){
  if (data) {
    data->append(ptr, size*nmemb);
    return size*nmemb;
  }
  else return 0;
}

/**
 * Получает содержимое страницы по ссылке link
 * @param link Ссылка на страницу
 * @return Строка с содержимым страницы
 */
std::string curlGet(string link){
  std::cout << "Read to memory" << '\n';
  CURL *curl;
  std::string content;
  curl = curl_easy_init();
  if(curl){
    curl_easy_setopt(curl, CURLOPT_URL, link.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlClbck);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
    CURLcode res = curl_easy_perform(curl);
    if (res == CURLE_OK) {
      curl_easy_cleanup(curl);
      return content;
    }else std::cerr << curl_easy_strerror(res) << std::endl;
    curl_easy_cleanup(curl);
  }
  return "";
}



Код второго способа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
  /**
   * Скачивает страницу по ссылке link в файл,
   * затем считывает файл в строку
   * @param link Ссылка на страницу
   * @return Строка с содержимым страницы
   */
  std::string systemGet (std::string link) {
    std::cout << "Read to file" << '\n';
    std::string res = "";
    string curl = "curl -o curl.html '" + link + "' -k > /dev/null 2>&1";
    system(curl.c_str());
    /*
      Здесь код считывания файла в строку res
      приводить его не буду, ибо он прост, но объёмен
    */
    return res;
  }



Тестируем функции:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
  unsigned int start_time, end_time,work_time;
  
  start_time = clock();
  std::string tmp1 = gurlGet(link);
  end_time = clock();
  work_time = end_time - start_time;
  cout << "Libcurl time: " << work_time << '\n'; 
    
  start_time =  clock();
  std::string tmp2 = systemGet(link);
  end_time = clock();
  work_time = end_time - start_time;
  cout << "System  time: " << work_time << '\n'; 

  cout << "Length tmp1: " << std::to_string(tmp1.length()) << '\n';
  cout << "Length tmp2: " << std::to_string(tmp2.length()) << '\n';



Вывод:

Код: plaintext
1.
2.
3.
4.
5.
Read to memory
Libcurl time: 20379
Read to file
System  time: 4646
Length tmp1: 114953
Length tmp2: 114953

Удивительно, но факт: скачать страницу в файл и считать из него в строку получается в 3 раза быстрее! Почему так медленно работает libcurl по сравнению с вызовом внешней программы?
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446550
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В экспериментах надо учитывать эффект прогрева сети, проксей и состояния ОС.
Я-бы предложил сделать явный запуск двух функций хотя-бы 5 или 7 раз чередуя
их через чет-нечёт и усреднить время.

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

Иногда - дьявол в деталях.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446554
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
14:09, axsmak
Код: sql
1.
2.
     data->append(ptr, size*nmemb);
     return size*nmemb;



Дай угадаю: считывание идёт по одному символу?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446560
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonВ экспериментах надо учитывать эффект прогрева сети, проксей и состояния ОС.
Я-бы предложил сделать явный запуск двух функций хотя-бы 5 или 7 раз чередуя
их через чет-нечёт и усреднить время.
Я сначала написал "ленивый вариант" с system и прогнал десяток страниц в цикле.
Потом, в надежде на ускорение, написал функцию на libcurl и тот же цикл отработал гораздо медленнее. Поэтому и начал проводить тесты и замеры.
Тесты запускались не раз и в разных комбинациях. Результат один.

maytonПлюс я-бы заметил что загадочный закомментированный код где читается файл
в строку может содержать ошибки которые приводят к замедлениям.
В том-то и подвох, что эта функция работает гораздо быстрее.
Код: sql
1.
2.
3.
4.
5.
6.
7.
  int i=0;
  std::ifstream f(fname);
  while (!f.eof()) {
    f.get(s[i]);
    i++;
  }
  f.close();
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446562
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovДай угадаю: считывание идёт по одному символу?..

Это коллбэк. Привязан тут: curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlClbck);
ptr - указатель на принимаемые данные.
size - размер принимамого блока данных
nmemb - общее количество блоков данных, объем принимаемой информации определяется как size * nmemb
То есть size определяет сам curl
К тому же в предыдущем комментарии я показал код считывания из файла. Там точно по одному символу. Вполне справедливо для теста
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446577
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
axsmak,

еще есть вариант, что твое приложение линкует дебаг(неоптимизированную) версию курла, а исполняет релиз(оптимизированную)

но 20с против 4с - это больше похоже на dns resolve или что то такое
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446580
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может дело в этом:
Код: plaintext
1.
end_time = clock();


clock() в линуксе меряет время работы процессора, т.е. запустив другой процесс через system() время останавливается.

Попробуй заменить clock() на std::chrono
Например так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
// Время с момента первого вызова, мсек
static int64_t lite_time_now() {
	static std::chrono::steady_clock::time_point t = std::chrono::steady_clock::now();
	std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
	std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t);
	return (int64_t)(time_span.count() * 1000);
}

...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446586
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
axsmak
Код: sql
1.
2.
3.
4.
5.
6.
7.
size_t curlClbck( char *ptr, size_t size, size_t nmemb, std::string* data){
  if (data) {
    data->append(ptr, size*nmemb);
    return size*nmemb;
  }
  else return 0;
}


Тут может быть тормоз если curlClbck() многократно вызывается во время скачивания одного файла. Т.к. string::append() выделяет память под новую строку и делает копию каждый раз.

Попробуй сразу зарезервировать сколько надо
Код: plaintext
1.
2.
3.
4.
std::string curlGet(string link){
...
  std::string content;
  content.reserve(1000000);
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446588
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для чистоты эксперимента лучше вообще замени добавление в строку на запись в файл. Тогда твой код будет делать тоже самое что и system("curl")
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446664
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция curlGet() не монолитна. Она состоит из нескольких последовательно вызываемых методов libcurl
каджый из которых потребляет своё время. Эти 20379 милисекунд распределены неоднородно по этим
методам.

Неплохо было-бы детализировать сколько сколько каждый занял.

Далее получив картинку - подумаем почему много потребляет основной потребитель. Здесь
могут быть варианты. Синхронность-асинхронность. Utf-0/ISO-8859-1.

И не точная аналогия между system("curl....") и котом который использует curl_eazy. Почему мы решили
что он эквивалентен? ХЗ.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446690
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonПочему мы решили
что он эквивалентен? ХЗ.
По эквивалентному результату.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446702
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Самое верное замечание было дано Dima T - clock() замеряет процессорное время используемое моим приложением. Во время выполнения внешней программы curl моё приложение почти не использует процессорное время.

С применением его lite_time_now() тесты показали примерно следующее время:
libcurl - 700 мск

system - 550 мск

Затем я изменил тест, прогоняя 10 разных страниц в цикле. И прогонял цикл несколько раз c разрывом в пару секунд. Так вот, цикл с system всегда показывает 5400-6000 мск, а libcurl в первый цикл показывает 7500-8000 мск, а последуюющие 5000-5200 мск. Стоит подождать некоторое время и libcurl опять остывает.

Кстати, до тестов я сделал резервирование памяти под строку результата content.reserve(1000000); Потом убрал её и скорость незначительно, но возрасла. Теперь libcurl, после разогрева показывает 4800-5000 мск, что, наконец-то превосходит system

Теперь осталось разобраться почему libcurl тормозит во время первого запуска. Какие мысли будут, господа?
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446704
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
axsmakТеперь осталось разобраться почему libcurl тормозит во время первого запуска. Какие мысли будут, господа?
К DNS обращается при первом вызове. При последующих к локальному кэшу. Поставь первым вызов system(), будет на нем тормозить.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446706
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Логи тестов
libcurl первый запуск
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
База создана
----------------
Page 1 begin 
Read to memory
Page 1 end 
Record count 50
----------------
Page 2 begin 
Read to memory
Page 2 end 
Record count 50
----------------
Page 3 begin 
Read to memory
Page 3 end 
Record count 50
----------------
Page 4 begin 
Read to memory
Page 4 end 
Record count 50
----------------
Page 5 begin 
Read to memory
Page 5 end 
Record count 50
----------------
Page 6 begin 
Read to memory
Page 6 end 
Record count 50
----------------
Page 7 begin 
Read to memory
Page 7 end 
Record count 50
----------------
Page 8 begin 
Read to memory
Page 8 end 
Record count 12
----------------
Page 9 begin 
Read to memory
Page 9 end 
Record count 0
----------------
Cycle time: 7957
База успешно разрушена

ВЫПОЛНЕНИЕ FINISHED; значение выхода 0,; в реальном времени: 7s; пользователь: 20ms; система: 340ms


libcurl следующий запуск
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
База создана
----------------
Page 1 begin 
Read to memory
Page 1 end 
Record count 50
----------------
Page 2 begin 
Read to memory
Page 2 end 
Record count 50
----------------
Page 3 begin 
Read to memory
Page 3 end 
Record count 50
----------------
Page 4 begin 
Read to memory
Page 4 end 
Record count 50
----------------
Page 5 begin 
Read to memory
Page 5 end 
Record count 50
----------------
Page 6 begin 
Read to memory
Page 6 end 
Record count 50
----------------
Page 7 begin 
Read to memory
Page 7 end 
Record count 50
----------------
Page 8 begin 
Read to memory
Page 8 end 
Record count 12
----------------
Page 9 begin 
Read to memory
Page 9 end 
Record count 0
----------------
Cycle time: 5766
База успешно разрушена

ВЫПОЛНЕНИЕ FINISHED; значение выхода 0,; в реальном времени: 5s; пользователь: 10ms; система: 320ms


system любой запуск
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
База создана
----------------
Page 1 begin 
Read to file
Page 1 end 
Record count 50
----------------
Page 2 begin 
Read to file
Page 2 end 
Record count 50
----------------
Page 3 begin 
Read to file
Page 3 end 
Record count 50
----------------
Page 4 begin 
Read to file
Page 4 end 
Record count 50
----------------
Page 5 begin 
Read to file
Page 5 end 
Record count 50
----------------
Page 6 begin 
Read to file
Page 6 end 
Record count 50
----------------
Page 7 begin 
Read to file
Page 7 end 
Record count 50
----------------
Page 8 begin 
Read to file
Page 8 end 
Record count 12
----------------
Page 9 begin 
Read to file
Page 9 end 
Record count 0
----------------
Cycle time: 6178
База успешно разрушена

ВЫПОЛНЕНИЕ FINISHED; значение выхода 0,; в реальном времени: 6s; пользователь: 70ms; система: 410ms
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446707
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TК DNS обращается при первом вызове. Реально ли программно реализовать что-то вроде кэша dns или просто забить на это?
Просто напрягает, что тормозит весь цикл, а не, хотя бы, первый вызов функции
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446709
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T, Совершенно верно
авторCURLOPT_DNS_CACHE_TIMEOUT - set life-time for DNS cache entries
By default, libcurl caches this info for 60 seconds.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446717
axsmak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всё нашёл.
Код: plaintext
1.
curl_easy_setopt(curl, CURLOPT_RESOLVE, host);


Жёстко прописал айпи сервера в настройки курл.
Кроме того вынес инициализацию из функции и вызываю в начале работы.
Определил неймспейс для работы с курлом, где написал функции инициализации, закрытия и выполнения запроса.
Скорость возросла в полтора раза в сравнении с system
Всем спасибо, код прилагаю

Буст libcurl
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
namespace crl {  
  CURL *curl;
  std::string content;
  struct curl_slist *host=NULL; 
  
  bool prepare () {
    curl = curl_easy_init();
    if (curl) {
      host = curl_slist_append(host, "host.com:443:222.222.222.222");
      curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlClbck);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
      std::cout << "Curl prepared" << '\n';
      return true;
    } else return false;
  }
  
  void close () {
    if (curl) {
      curl_easy_cleanup(curl);
      std::cout << "Curl closed" << '\n';
    }
  }

  size_t curlClbck( char *ptr, size_t size, size_t nmemb, string* data){
    if (data) {
      data->append(ptr, size*nmemb);
      return size*nmemb;
    } else return 0;
  }
  
  string exec(string link){
    content = "";
    if(curl){
      curl_easy_setopt(curl, CURLOPT_URL, link.c_str());
      CURLcode res = curl_easy_perform(curl);
      if (res == CURLE_OK) {
        return content;
      }else std::cerr << curl_easy_strerror(res) << std::endl;    
    }
    return "";
  }
}

int main(int argc, char** argv) {
  crl::prepare();
  /*
    Работа в цикле с crl::exec(link);
  */
  crl::close();
}

...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446738
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
axsmak,

почему не сделать
CURL *curl = nullptr;
?

иначе довольно опасно. значение переменно не определено, но производится проверка.
если там будет "мусор" проверка может пройти, но работать не будет(в лучшем случае).

Ну и не понимаю я таких проверка на nullptr как
if(curl){

почему не сделать явное условие?
видимо, -Wall -Werror не используются
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446745
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_kНу и не понимаю я таких проверка на nullptr как
if(curl){

почему не сделать явное условие?
видимо, -Wall -Werror не используются
Это идиома с/с++. С чего вдруг должны быть предупреждения?
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446748
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
axsmakЖёстко прописал айпи сервера в настройки курл.
IP поменяется и долго будешь искать почему работать перестало.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446751
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyalex_kНу и не понимаю я таких проверка на nullptr как
if(curl){

почему не сделать явное условие?
видимо, -Wall -Werror не используются
Это идиома с/с++. С чего вдруг должны быть предупреждения?
да, нет варнинга. а я бы сделал! :)
чтобы в условиях был только буль
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446754
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_kAnatoly Moskovskyпропущено...

Это идиома с/с++. С чего вдруг должны быть предупреждения?
да, нет варнинга. а я бы сделал! :)
чтобы в условиях был только буль
0, NULL и false это одно и тоже. Это просто надо знать если пишешь на С/С++.
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446757
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Talex_kпропущено...

да, нет варнинга. а я бы сделал! :)
чтобы в условиях был только буль
0, NULL и false это одно и тоже. Это просто надо знать если пишешь на С/С++.
при это NULL - это просто символьное имя, которое может быть чем угодно :)
Это тоже надо знать :)
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446758
alex_k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
int main()
{
    float NULL = 3.14f;
    if (NULL) throw "what?";
    return 0;
}
...
Рейтинг: 0 / 0
Как ускорить libcurl?
    #39446761
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_k
Код: plaintext
1.
2.
3.
4.
5.
6.
int main()
{
    float NULL = 3.14f;
    if (NULL) throw "what?";
    return 0;
}


Не компилируется.
...
Рейтинг: 0 / 0
25 сообщений из 31, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как ускорить libcurl?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]