Skip to content
This repository was archived by the owner on Jun 1, 2026. It is now read-only.
This repository was archived by the owner on Jun 1, 2026. It is now read-only.

Need a way to change the CHUNK_SIZE value at runtime. #8

Description

@infgeoax

Or am I using cpprest in the wrong way?

Our application normally transfers data (using HTTP GET) of several hundred megabytes, the default 64 Kb chunk size seems too small for optimal download rate. Changing the value to 5 Mb can reduce download time of 2 Gb data from 2minutes to 28 seconds.

The demo code, which just allocates the requested data in-memory and send them:

#include <Windows.h>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <cpprest/streams.h>
#include <cpprest/filestream.h>
#include <cpprest/producerconsumerstream.h>
#include <algorithm>
#include <chrono>
#include <iostream>
#include <string>

using namespace concurrency::streams;
using namespace web;
using namespace http;
using namespace http::experimental::listener;

int main(int argc, char *argv[]) {

    http_listener listener(L"http://*:8080/bytes");

    listener.support(methods::GET, [](http_request &request) {

        auto q = web::uri::split_query(request.request_uri().query());

        // default: 100 MB of data
        std::size_t bytes_to_write = 100 * 1048576;

        if (q.find(L"b") != std::end(q)) {
            bytes_to_write = std::stoul(q[L"b"]);
        }
        if (q.find(L"kb") != std::end(q)) {
            bytes_to_write = std::stoul(q[L"kb"]) * 1024;
        }
        if (q.find(L"mb") != std::end(q)) {
            bytes_to_write = std::stoul(q[L"mb"]) * 1024 * 1024;
        }

        request.reply(status_codes::OK, std::string(bytes_to_write, '+'));
        std::cout << "Sent " << bytes_to_write << "bytes\n";
    });

    listener.open().wait();

    std::wcout << "Listening on " << listener.uri().port() << std::endl;

    while (true) {
        try {
            Sleep(1);
        }
        catch (...) {
            break;
        }
    }

    listener.close().wait();

    return 0;
}

And using curl for testing:

curl -o NUL http://localhost:8080/bytes?mb=2000

Using 64Kb chunk size:

[root@localhost ~]# curl -o NUL 10.50.10.51:8080/bytes?mb=2000
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 2000M  100 2000M    0     0  15.7M      0  0:02:06  0:02:06 --:--:-- 14.8M

Using 5Mb chunck size:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 2000M  100 2000M    0     0  69.2M      0  0:00:28  0:00:28 --:--:-- 77.1M

Activity

  1. kavyako commented on Oct 29, 2015

    @kavyako
    Contributor

    You could also expose the chunk_size option in http_listener_config class.
    This is how chunk size is provided as an option on the http_client.

    Our goal is to stay uniform across all the platforms that we support. So ideally we would prefer solutions that can be implemented across the board.

    The discussion thread on codeplex also has some details https://casablanca.codeplex.com/discussions/646631

    Thanks
    Kavya.

  2. kavyako commented on Nov 2, 2015

    @kavyako
    Contributor

    hey wongpsw

    Please note, to contribute to the project, you will need to sign our contributor license agreement (CLA). Once you've signed you can email it directly to me at kavyako at Microsoft dot com or askcasablanca at Microsoft dot com.

    Thanks
    Kavya

  3. dpjudas commented on Feb 3, 2022

    @dpjudas

    I believe the correct fix to this issue is actually to add the HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA flag to the HttpSendResponse and HttpSendResponseEntityBody calls in http_server_httpsys.cpp. Adding this flag increased the throughput from 15 mbit/s to 300 mbit/s for my test transfer with a 40 ms ping to the server.

    This flag makes http.sys automatically size the send buffer based on the ideal send backlog (ISB). To quote the MSDN documentation for SIO_IDEAL_SEND_BACKLOG_CHANGE:

    "When sending data over a TCP connection using Windows sockets, it is important to keep a sufficient amount of data outstanding (sent but not acknowledged yet) in TCP in order to achieve the highest throughput. The ideal value for the amount of data outstanding to achieve the best throughput for the TCP connection is called the ideal send backlog (ISB) size. The ISB value is a function of the bandwidth-delay product of the TCP connection and the receiver's advertised receive window (and partly the amount of congestion in the network)."

    Or in other words, manually adjusting the chunk size will never completely work as you can't predict the ideal size. Luckily we can opt-in to the kernel managing this for us by adding the HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions