aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2021-07-16 15:38:38 +0200
committerKim Alvefur <zash@zash.se>2021-07-16 15:38:38 +0200
commit56fef6867fc30100b77be1146e4e70bf25970e6b (patch)
tree7da16d19cdef6f3c5bc0befbe4583a7e7675e19c
parent07afd46b58ce91ac96a64140c3a1b7479a6e01fc (diff)
downloadprosody-56fef6867fc30100b77be1146e4e70bf25970e6b.tar.gz
prosody-56fef6867fc30100b77be1146e4e70bf25970e6b.zip
net.server_epoll: Avoid allocating a buffer table for single writes
writebuffer is now string | { string } Saves the allocation of a buffer table until the second write, which could be rare, especially with opportunistic writes.
-rw-r--r--net/server_epoll.lua31
1 files changed, 20 insertions, 11 deletions
diff --git a/net/server_epoll.lua b/net/server_epoll.lua
index 6ab07996..8db18930 100644
--- a/net/server_epoll.lua
+++ b/net/server_epoll.lua
@@ -471,11 +471,18 @@ function interface:onwritable()
self:onconnect();
if not self.conn then return; end -- could have been closed in onconnect
local buffer = self.writebuffer;
- local data = #buffer == 1 and buffer[1] or t_concat(buffer);
+ local data = buffer or "";
+ if type(buffer) == "table" then
+ if buffer[2] then
+ data = t_concat(data);
+ else
+ data = buffer[1] or "";
+ end
+ end
local ok, err, partial = self.conn:send(data);
if ok then
self:set(nil, false);
- if cfg.keep_buffers then
+ if cfg.keep_buffers and type(buffer) == "table" then
for i = #buffer, 1, -1 do
buffer[i] = nil;
end
@@ -487,13 +494,13 @@ function interface:onwritable()
return ok;
elseif partial then
self:debug("Sent %d out of %d buffered bytes", partial, #data);
- if cfg.keep_buffers then
+ if cfg.keep_buffers and type(buffer) == "table" then
buffer[1] = data:sub(partial+1);
for i = #buffer, 2, -1 do
buffer[i] = nil;
end
else
- data.writebuffer = { data:sub(partial+1) };
+ data.writebuffer = data:sub(partial+1);
end
self:set(nil, true);
self:setwritetimeout();
@@ -517,11 +524,13 @@ end
-- Add data to write buffer and set flag for wanting to write
function interface:write(data)
local buffer = self.writebuffer;
- if buffer then
+ if type(buffer) == "table" then
t_insert(buffer, data);
- else
+ elseif type(buffer) == "string" then
self:noise("Allocating buffer!")
- self.writebuffer = { data };
+ self.writebuffer = { buffer, data };
+ elseif buffer == nil then
+ self.writebuffer = data;
end
if not self._write_lock then
if cfg.opportunistic_writes and not self._opportunistic_write then
@@ -539,7 +548,7 @@ interface.send = interface.write;
-- Close, possibly after writing is done
function interface:close()
- if self.writebuffer and self.writebuffer[1] then
+ if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then
self:set(false, true); -- Flush final buffer contents
self:setwritetimeout();
self.write, self.send = noop, noop; -- No more writing
@@ -578,7 +587,7 @@ end
function interface:starttls(tls_ctx)
if tls_ctx then self.tls_ctx = tls_ctx; end
self.starttls = false;
- if self.writebuffer and self.writebuffer[1] then
+ if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then
self:debug("Start TLS after write");
self.ondrain = interface.starttls;
self:set(nil, true); -- make sure wantwrite is set
@@ -687,7 +696,7 @@ local function wrapsocket(client, server, read_size, listeners, tls_ctx, extra)
created = realtime();
listeners = listeners;
read_size = read_size or (server and server.read_size);
- writebuffer = {};
+ writebuffer = nil;
tls_ctx = tls_ctx or (server and server.tls_ctx);
tls_direct = server and server.tls_direct;
id = conn_id;
@@ -811,7 +820,7 @@ function interface:resume_writes()
end
self:noise("Resume writes");
self._write_lock = nil;
- if self.writebuffer[1] then
+ if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then
self:setwritetimeout();
self:set(nil, true);
end