Skip to content

Add buf_read_size setting for WSGI configurable request body buffering#3586

Open
ixunio wants to merge 3 commits intobenoitc:masterfrom
ixunio:buf-size
Open

Add buf_read_size setting for WSGI configurable request body buffering#3586
ixunio wants to merge 3 commits intobenoitc:masterfrom
ixunio:buf-size

Conversation

@ixunio
Copy link
Copy Markdown

@ixunio ixunio commented Apr 11, 2026

This PR introduces wsgi-input-block-size setting to control buffer size for reading request data from the socket.

Cf this issue #2596 and this stalled PR #3068

Experiment

Benchmarks running Flask 3.1 and Gunicorn 25.3 on Python 3.12, on different environments / setup:

Code running

flask_app.py

from flask import Flask, Response, request


app = Flask(__name__)


@app.post("/upload")
def upload():
    start = time.perf_counter()
    body = request.get_data(cache=False)
    received = len(body)

    process_seconds = time.perf_counter() - start
    payload = json.dumps(
        {
            "framework": "flask",
            "received_bytes": received,
            "process_seconds": process_seconds,
        }
    ).encode("ascii")
    response = Response(payload, mimetype="application/json")
    response.headers["Content-Length"] = str(len(payload))
    response.headers["X-Framework"] = "flask"
    response.headers["X-Received-Length"] = str(received)
    response.headers["X-Process-Duration"] = f"{process_seconds:.9f}"
    return response

command

gunicorn --bind 0.0.0.0:18100 --workers 1 --worker-class sync --wsgi-input-block-size xxx flask_app:app

Results Relative throughput change versus `1kB` wsgi-input-block-size, shown as a positive percentage when bandwidth increases.
↓ Payload ↓ 2kB 4kB 8kB 16kB 32kB 64kB 128kB 256kB 512kB 1MB
1kB +24% +13% +7% +7% +5% +5% +22% +16% +11% +14%
10kB +28% +28% +34% +36% +35% +34% +38% +50% +44% +41%
50kB +50% +95% +60% +149% +83% +124% +89% +99% +131% +96%
100kB +34% +40% +64% +59% +16% +6% +80% +41% +57% +101%
200kB +29% +55% +75% +82% +50% +60% +67% +72% +105% +59%
500kB -1% +5% +2% -2% +4% +4% -2% -5% +10% -4%
1MB -2% -1% -6% +1% -0% -3% +3% +12% -1% -19%
2MB +15% +12% +17% +30% +4% +14% +21% +22% -3% -2%
5MB +13% +23% +23% +17% +30% +20% +17% +12% +10% -15%
10MB +13% +25% +27% +25% +26% +22% +19% +20% +11% -14%
50MB +17% +37% +42% +40% +45% +47% +42% +22% +43% +12%
100MB +24% +38% +47% +59% +53% +55% +45% +40% +48% +22%
250MB +24% +43% +59% +58% +61% +55% +52% +50% +29% +21%
500MB +34% +58% +57% +70% +67% +61% +55% +59% +46% +25%
1000MB +37% +54% +61% +70% +68% +67% +55% +60% +64% +30%

Findings

Note: these apply to WSGI sync workers. This parameter has no effect on ASGI configurations.

  • 🚀 Large Payloads (≥ 5MB): we see significant performance gains and high stability across all environments/setup. Variance remains low, making this a clear win for large data transfers.
  • ⚠️ Small Payloads (≤ 200kB): results are highly volatile. Due to significant variance between runs and environments, I cannot definitively categorize this as an improvement. I recommend benchmarking this within your specific infrastructure before tweaking wsgi-input-block-size.
  • 🤔 Interestingly, payloads near the 1MB mark show either zero improvement or slight regressions, regardless of the wsgi-input-block-size configuration. This behavior is consistent across different environments. Any insights into why we might be hitting a bottleneck specifically at the 1MB threshold @benoitc ?

Comment thread gunicorn/http/body.py Outdated
Copy link
Copy Markdown
Owner

@benoitc benoitc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! see my comments below. The PR looks good otherwise. If you can add an integration test that would be useful.

Comment thread gunicorn/config.py Outdated
Comment thread gunicorn/config.py Outdated
@benoitc
Copy link
Copy Markdown
Owner

benoitc commented Apr 25, 2026

@ixunio did you have the time to look at the review? feel free to ask if you have any questions

- Introduced `buf_read_size` setting to control buffer size for reading request data from the socket.
- Updated `Body` class to utilize `buf_read_size` for reading operations.
- Added validation for `buf_read_size` to ensure it is a positive integer.
- Enhanced tests to cover the new setting and its validation.
@ixunio
Copy link
Copy Markdown
Author

ixunio commented Apr 25, 2026

@ixunio did you have the time to look at the review? feel free to ask if you have any questions

thanks for your comments, I will look into it tomorrow!

ixunio and others added 2 commits April 26, 2026 08:09
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
@ixunio
Copy link
Copy Markdown
Author

ixunio commented Apr 26, 2026

@benoitc might as well rename the PR to reflect the new naming wsgi_input_block_size

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants