Skip to content

Add buf_read_size setting for WSGI configurable request body buffering - #3586

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

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

Conversation

@ixunio

@ixunio ixunio commented Apr 11, 2026

Copy link
Copy Markdown

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

@benoitc benoitc left a comment

Copy link
Copy Markdown
Owner

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

benoitc commented Apr 25, 2026

Copy link
Copy Markdown
Owner

@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

ixunio commented Apr 25, 2026

Copy link
Copy Markdown
Author

@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

ixunio commented Apr 26, 2026

Copy link
Copy Markdown
Author

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

@ixunio

ixunio commented Aug 4, 2026

Copy link
Copy Markdown
Author

@benoitc did you have the time to look at it?

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