-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixup response processing, enumerable bodies #3004
Conversation
d205d07
to
180406c
Compare
Never mind recent commits, accidentally clicked push... |
6f20970
to
f7db054
Compare
f7db054
to
a3ba077
Compare
a3ba077
to
85f5284
Compare
This is now just a 'fixup' PR. Main issue is fixing enumerable bodies. Improvements also made to 'string' and 'array' bodies. |
A note about cork/uncork. Remember that it dates back to remote console use (via sockets) a long time ago. Or, connections were a bit slower than. The Sinatra example code uses an enumerable body: stream do |out|
out << "It's gonna be legen -\n"
sleep 0.5
out << " (wait for it) \n"
sleep 1
out << "- dary!\n"
end When I first added a test, I dropped the times to After wrestling with it for a while, I recalled that cork/uncork is about both buffered bytes that haven't been transmitted, and time between data, in that it will only hold data for so long. With the lower times, the test would only pass if the amount of data was increased to exceed the limits in cork/uncork. But, when I increased the times from |
Found an issue with turbo-rails. The response body says it responds to Simple fix, but I want to investigate further. |
Update - I've got CI running turbo-rails testing using Rails 6.1 and 7.0. It's intermittently failing, trying to figure out why... EDIT: Most, but not all of the CI failures are with Rails 6.1. Of course, I can't repo locally... |
Where? Something the Puma repo should have? |
While this PR makes https://github.com/sinatra/sinatra/blob/v3.0.2/examples/stream.ru work again, I still have problems with my app, running from dentarg/testssl.web@f1fbd41 and this branch, the request returns immediately:
Logs from Puma
|
Thanks for testing. I've got changes to this PR. As mentioned, I've added a workflow using turbo-rails. I just ran the test. Both jobs failed the first time, I immediately reran it, and both passed. Locally, it always passes. Trying to figure out why. |
Slow CI? Maybe possible to simulate locally using Docker? |
In a branch that I'll cherry-pick back into this PR. Two jobs, last run took a minute. It's a little brittle, but it works. Most recent run. The 'test' CI run.
I think so. It uses The branch is 00-turbo-rails in my fork, MSP-Greg/puma. Can you check with Note the speed improvements shown in the first post. Some real gains. Granted, that's Puma's processing, and a lot of responses are constrained by the app's response time... |
It behaves the same as I reported above, |
Thanks. I’ll try it locally. Interested to find the issue… |
How do I generate EDIT: installed 'bsdmainutils', ran |
That's https://testssl.sh/, if your WSL environment have Homebrew you can install it with |
Haven't tried it but spawning something else that's outputting to stdout and stderr should be the same thing I guess. |
Thanks. Seem to be up and running. A |
Ok, Installed homebrew, then testssl. Running
The puma terminal shows:
If you could test again... Thanks. |
Yes it works now |
c537474
to
b3dd077
Compare
lib/puma/io_buffer.rb
Outdated
@@ -22,6 +22,16 @@ def to_s | |||
read | |||
end | |||
|
|||
# Read & Reset - returns contents and resets | |||
# @return [String] StringIO contents | |||
def rd_and_rst |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def rd_and_rst | |
def read_and_reset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, pushed back into 'Updates for response body processing'
lib/puma/request.rb
Outdated
res_body.each { |part| length += part.bytesize; body << part } | ||
end | ||
resp_info[:content_length] = length | ||
if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary) && array_body.is_a?(Array) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary) && array_body.is_a?(Array) | |
if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to test this. I recall that one of the Rails wrapped responses/bodies returned nil
when to_ary
was called. Not.sure.
Kicking myself for not adding a comment about it. Give me a bit.
EDIT: Sorry, long day. If res_body.to_ary
is nil
, the third segment isn't needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I see... I think if to_ary
returns nil, you can assume there is no body. This is out of alignment with the Rack spec in any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Pushed back into 'Updates for response body processing'
lib/puma/request.rb
Outdated
@@ -225,12 +235,13 @@ def prepare_response(status, headers, res_body, requests, client) | |||
io_buffer << line_ending | |||
|
|||
if response_hijack | |||
fast_write_str socket, io_buffer.to_s | |||
fast_write_str socket, io_buffer.rd_and_rst |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fast_write_str socket, io_buffer.rd_and_rst | |
fast_write_str socket, io_buffer.read_and_reset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, pushed back into 'Updates for response body processing'
test/test_cli.rb
Outdated
@@ -25,6 +25,8 @@ def setup | |||
|
|||
@events = Puma::Events.new | |||
@events.on_booted { @ready << "!" } | |||
|
|||
@puma_vers_re = "\\d+.\\d+.\\d+(\\.[a-z\\d]+)?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@puma_vers_re = "\\d+.\\d+.\\d+(\\.[a-z\\d]+)?" | |
@puma_version_pattern = "\\d+.\\d+.\\d+(\\.[a-z\\d]+)?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, pushed back into test_cli.rb - allow for Puma version like 6.0.1.dev or 6.0.1.rc1
b3dd077
to
a0c8b80
Compare
LGTM. |
a0c8b80
to
a37953f
Compare
Description
PR #2896 added code to collect members of response bodies that are Arrays or Enums, and allow a size threshold that waits to send the collected bytes only when they exceed it. Previously, if the response body consisted of many small strings, each string was written. #2896 collects them, and only writes when they exceed the threshold. This may affect TTFB (time-to-first-byte). The limit value was also too high in #2896.
This causes issues with Enum bodies that mimic a streaming body. The size threshold has been removed for Enum bodies, but remains for true Array bodies.
Previously, due to the handling of Enum bodies, test code in Sinatra failed. The code is checked in an added test, `test_streaming_enum_body'.
Using the benchmarks in benchmark/local, this PR shows:
Using 5.6.5 and configuring
wait_for_less_busy_worker
to match current master:'Requests per second' has greatly increased for body sizes below 100kB, above increases are smaller.
Closes #3000.
Your checklist for this pull request
[ci skip]
to the title of the PR.#issue
" to the PR description or my commit messages.