Я выполняю HTTP-запросы от моей программы на C++ до своего PHP-скрипта с помощью libcurl.
Первая версия easy_ ниже работает хорошо, однако она довольно медленная (12 запросов в секунду на localhost).
Ничего странного - я получил аналогичные результаты, используя ab -n 1000 -c 1
.
С другой стороны, ab -n 1000 -c 100
работает намного лучше с 600 запросами в секунду.
Дело в том, что использование libcurl multi не похоже на одновременное. Я использовал только слегка модифицированный пример кода, и результат также составляет около 12 req/s.
Нет разницы между curl_easy и curl_multi
Я правильно понимаю curl_multi? Как я могу достичь результатов, похожих на ab?
PS. Я знаю, что оба кода немного отличаются друг от друга, однако почти все время тратится на завиток.
easy_ путь:
CURL *curl;
CURLcode response; // HTTP response
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/process.php");
while(true)
{
if(!requestsQueue.empty())
{
mtx.lock();
string data = requestsQueue.front();
requestsQueue.pop();
mtx.unlock();
const char *post = data.c_str(); //convert string to char used by CURL
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
do
{
response = curl_easy_perform(curl);
} while(response != CURLE_OK);
}
else
{
//there are no request to perform, so wait for them
cout << "Sleeping...\n";
sleep(2);
continue;
}
}
//curl_easy_cleanup(curl);
}
else
{
cout << "CURL init failed!\n";
}
Мульти путь:
CURLM *multi_handle;
int still_running; /* keep number of running handles */
/* init a multi stack */
multi_handle = curl_multi_init();
/* add the individual transfers */
for(int i=1;i<=300;i++)
{
CURL *handle;
handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, "http://localhost/process.php");
curl_multi_add_handle(multi_handle, handle);
}
/* we start some action by calling perform right away */
curl_multi_perform(multi_handle, &still_running);
do {
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(multi_handle, &curl_timeo);
if(curl_timeo >= 0) {
timeout.tv_sec = curl_timeo/1000;
if(timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
default:
/* timeout or readable/writable sockets */
curl_multi_perform(multi_handle, &still_running);
break;
}
} while(still_running);
curl_multi_cleanup(multi_handle);
curl_easy_cleanup(http_handle);
return 0;
Я использовал только curl в очень простых настройках, но вы уверены, что 'curl_easy_setopt' - это правильная вещь при использовании' curl_multi ... '? –
@MatsPetersson: да. Обратите внимание, что URL-адрес - это опция простого дескриптора, а не multi. Каждый запрос может быть связан с разными URL-адресами. – user2461440
@ user2461440 не называть 'mutex.lock' и' mutex.unlock' напрямую использовать блок и ['std :: lock_guard'] (http://en.cppreference.com/w/cpp/thread/lock_guard) быть безопасным исключением. – Mgetz