-
Notifications
You must be signed in to change notification settings - Fork 113
Added request body buffer regeneration #43
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
Conversation
lib/resty/upload.lua
Outdated
end | ||
|
||
local function finish_body(self) | ||
if self.resore_body then |
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.
typo here
lib/resty/upload.lua
Outdated
return nil, err | ||
end | ||
|
||
return setmetatable({ | ||
sock = sock, | ||
size = chunk_size or CHUNK_SIZE, | ||
line_size = max_line_size or MAX_LINE_SIZE, | ||
resore_body = restore_body_buffer or false, |
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.
resore
-> restore
? Also or false
not needed, though, doesn't hurt much either.
lib/resty/upload.lua
Outdated
@@ -145,6 +181,8 @@ local function read_body_part(self) | |||
|
|||
local data = sock:receive(2) | |||
if data == "--" then | |||
append_body(self, "\r\n--" .. self.boundary .. "--\r\n") |
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.
We always concatenate strings here. Even when restore_body
is false
. Same thing happens in other append_body
places. Maybe just checking the boolean variable doesn't warrant its own function and that can be inlined. Then we also solve this issue.
lib/resty/upload.lua
Outdated
|
||
local function discard_line(self) | ||
local read_line = self.read_line | ||
|
||
local line, err = read_line(self.line_size) | ||
if not line then | ||
finish_body(self); |
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.
semicon ;
not needed.
I fixed the typo and implemented you suggestion. I am not sure though if it is faster to append multiple times like I have done now or to create a new string and append once. |
Yes, previously you created strings even when not appending anything. |
lib/resty/upload.lua
Outdated
@@ -93,21 +111,39 @@ function _M.set_timeout(self, timeout) | |||
return sock:settimeout(timeout) | |||
end | |||
|
|||
local function append_body(self, ...) |
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 don't think you need to use varargs here, as you only ever have at most 3 args. Also you don't need to create a table with varargs, you can select("#", ...)
and select(1, ...)
.
@dylandreimerink thanks for working on this. I think that one thing to add is test(s). |
I took a look at the source code for ngx.req.append_body which is quite big and does a memcpy. So I think it is best to ditch the whole idea of a separate function ( like u suggested before ) and concatenate a single string in the main functions. Then calling ngx.req.append_body once right before ngx.req.finish_body to minimize overhead. I will work on that as soon as I have time |
This should do it. I replaced the appending by a string buffer which should make it more performant. If this passes the only thing left to do is to make tests. I have to admit however that I do not yet understand how this unit test framework works, so i may need a little bit of guidance. |
I am not sure what does it add to buffer to Lua table? Just more complexity. For real string buffer we need something like this: LuaJIT/LuaJIT#14 I think that just |
Working from the assumption that append_body is relatively speaking slow since it has to copy data from the lua vm to nginx the idea is to keep the data in lua for as long as possible. Since lua strings are immutable they have to be recreated and copied every time you want to concatenate to an existing string. The solution would be to have a native implementation of a mutable string or string buffer. But since I have little hope for that in the near future I think the use of a table to store a list of strings and concatenating them once is the best option. The reason I am going to these lengths is because I will be using this feature in a proxy with a high throughput, so for me personally speed and optimization is quite important. So in light of that I will benchmark the different solutions so we can make an informed decision instead of having to work based on assumptions. |
I made the benchmark. The results are to me a bit unexpected. I tested 4 variations and the original, the summarized results are as follows:
The variation without the string buffer is the fastest but the difference is almost negligible. |
@bungle Have you had time to look at the last changes? |
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 left some more comments. Mostly style related changes. Biggest pressing issue right now is that this doesn't yet have tests. I think we should have good test suite that also tests with invalid input. Should we actually have some kind of internal error handler here that runs in case of error happens, and then just writes rest of the buffer back, e.g. leaving the body intact.
return nil, err | ||
end | ||
|
||
local read_line, err = sock:receiveuntil("\r\n") | ||
if not read_line then | ||
|
||
if restore_body_buffer then | ||
ngx_finish_body() |
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.
The previous read, on line 72, was successful, but we didn't write the request body back, is this intended? Maybe there are many similar cases in code, but no easy way to solve? E.g. on errors we don't write the request body back.
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.
The sock:receiveuntil returns an iterator Lua function and doesn't actually read data from the buffer so there is noting to restore.
return nil, err | ||
end | ||
|
||
if self.restore_body_buffer then | ||
ngx_append_body(line .. "\r\n") |
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 think this is fine, but you could also have:
ngx_append_body(line)
ngx_append_body("\r\n")
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 don't see any point in not concatenating the string here, the same goes for the rest of the remarks regarding concatenation.
@@ -145,6 +181,10 @@ local function read_body_part(self) | |||
|
|||
local data = sock:receive(2) | |||
if data == "--" then | |||
if self.restore_body_buffer then | |||
ngx_append_body("\r\n--" .. self.boundary .. "--\r\n") |
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.
Same here:
ngx_append_body("\r\n--")
ngx_append_body(self.boundary)
ngx_append_body(ngx_append_body("--\r\n"))
Not a big deal.
@@ -161,10 +201,18 @@ local function read_body_part(self) | |||
end | |||
end | |||
|
|||
if self.restore_body_buffer then | |||
ngx_append_body("\r\n--" .. self.boundary .. "\r\n") |
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.
This coud be cached before the while loop:
local boundary_delimiter = "\r\n--" .. self.boundary .. "\r\n"
And then here:
ngx_append_body(boundary_delimiter)
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.
There is no while loop surrounding this line
@@ -232,7 +296,14 @@ local function read_preamble(self) | |||
while true do | |||
local preamble = read2boundary(size) | |||
if not preamble then | |||
if self.restore_body_buffer then | |||
ngx_append_body("--" .. self.boundary) |
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.
Ditto here:
ngx_append_body("--")
ngx_append_body(self.boundary)
Yes, bikeshedding :-).
local dummy, err = read_line(1) | ||
if dummy then | ||
if self.restore_body_buffer then | ||
ngx_finish_body() | ||
end |
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.
new line after this.
return nil, "line too long: " .. line .. dummy .. "..." | ||
end | ||
|
||
if err then | ||
if self.restore_body_buffer then | ||
ngx_finish_body() | ||
end |
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.
new line after this.
@@ -122,6 +152,9 @@ local function discard_rest(self) | |||
while true do | |||
local dummy, err = sock:receive(size) | |||
if err and err ~= 'closed' then | |||
if self.restore_body_buffer then | |||
ngx_finish_body() | |||
end |
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.
new line after this.
@@ -137,6 +170,9 @@ local function read_body_part(self) | |||
|
|||
local chunk, err = read2boundary(self.size) | |||
if err then | |||
if self.restore_body_buffer then | |||
ngx_finish_body() | |||
end |
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.
new line after this.
@@ -174,15 +222,28 @@ local function read_header(self) | |||
|
|||
local line, err = read_line(self.line_size) | |||
if err then | |||
if self.restore_body_buffer then | |||
ngx_finish_body() | |||
end |
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.
new line after this.
I made a fix for issue #41 and #42.
Optional support for body buffer regeneration.