Skip to content

http_listener is getting slower over time on Windows #46

Closed
@wdx04

Description

@wdx04

I wrote a simple http server using http_listener, with a simple client to test the performance of the server. Then I observed that the http server is getting slower after every run of the client, and its memory consumption is increasing:

PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1380 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1468 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1572 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1642 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1774 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 1952 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 2062 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 2153 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 2210 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 2352 ms.
PS C:\Develop\Tests\testrestserver\Release> ./testrestclient.exe
Sending 1000 requests...
Ellapsed Time: 2420 ms.

Testing Environment:
Hardware: AMD A10-5757M APU, 8GB RAM
Operating System: Windows 8.1 x64
Compiler: Visual C++ 2013 Update 2
C++ REST SDK version: 2.7

I also run the same test on Ubuntu 14.04 LTS on the same machine, the Boost.Asio-based http_listener do not have the problem.

Server source code:

#include <stdio.h>
#include <cpprest/uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/asyncrt_utils.h>
#pragma comment(lib, "cpprest120_2_7.lib")
#pragma comment(lib, "bcrypt.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "winhttp.lib")
#pragma comment(lib, "httpapi.lib")

using namespace web;
using namespace http;
using namespace utility;
using namespace http::experimental::listener;

class CommandHandler
{
public:
    CommandHandler() {}
    CommandHandler(utility::string_t url);

    pplx::task<void> open() { return m_listener.open(); }
    pplx::task<void> close() { return m_listener.close(); }

private:
    void handle_get_or_post(http_request message);

    http_listener m_listener;
};

CommandHandler::CommandHandler(utility::string_t url) : m_listener(url)
{
    m_listener.support(methods::GET, std::bind(&CommandHandler::handle_get_or_post, this, std::placeholders::_1));
    m_listener.support(methods::POST, std::bind(&CommandHandler::handle_get_or_post, this, std::placeholders::_1));
}

void CommandHandler::handle_get_or_post(http_request message)
{
    message.reply(status_codes::OK, "ACCEPTED");
};

int main(int argc, char argv[])
{
    try
    {
        utility::string_t address = U("http://*:8080");

        uri_builder uri(address);
        auto addr = uri.to_uri().to_string();

        CommandHandler handler(addr);
        handler.open().wait();

        ucout << utility::string_t(U("Listening for requests at: ")) << addr << std::endl;
        ucout << U("Press ENTER key to quit...") << std::endl;
        std::string line;
        std::getline(std::cin, line);

        handler.close().wait();
    }
    catch (std::exception& ex)
    {
        ucout << U("Exception: ") << ex.what() << std::endl;
        ucout << U("Press ENTER key to quit...") << std::endl;
        std::string line;
        std::getline(std::cin, line);
    }

    return 0;
}

Client source code:

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <chrono>
#include <cpprest/uri.h>
#include <cpprest/asyncrt_utils.h>
#include <cpprest/http_client.h>
#pragma comment(lib, "cpprest120_2_7.lib")
#pragma comment(lib, "bcrypt.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "winhttp.lib")

using namespace std;
using namespace web::http;
using namespace web::http::client;
using namespace utility;

#define N 1000

int _tmain(int argc, _TCHAR* argv[])
{
    cout << "Sending " << N << " requests..." << endl;
    auto t1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; i++)
    {
        http_client c(U("http://localhost:8080/"));
        c.request(methods::GET, uri_builder(U("/PASS")).to_string())
        .then([=](http_response resp)
        {
            resp.extract_string().get();
        }).wait();
    }
    auto t2 = std::chrono::high_resolution_clock::now();
    cout << "Ellapsed Time: " << chrono::duration_cast<chrono::milliseconds>(t2 - t1).count() << " ms." << endl;
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions