Mercurial > prosody-hg
comparison net/server_epoll.lua @ 11697:6c3d8aa3bbd9
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.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 16 Jul 2021 15:38:38 +0200 |
| parents | 917eca7be82b |
| children | 9a2a98621c73 |
comparison
equal
deleted
inserted
replaced
| 11696:917eca7be82b | 11697:6c3d8aa3bbd9 |
|---|---|
| 469 -- Called when socket is writable | 469 -- Called when socket is writable |
| 470 function interface:onwritable() | 470 function interface:onwritable() |
| 471 self:onconnect(); | 471 self:onconnect(); |
| 472 if not self.conn then return; end -- could have been closed in onconnect | 472 if not self.conn then return; end -- could have been closed in onconnect |
| 473 local buffer = self.writebuffer; | 473 local buffer = self.writebuffer; |
| 474 local data = #buffer == 1 and buffer[1] or t_concat(buffer); | 474 local data = buffer or ""; |
| 475 if type(buffer) == "table" then | |
| 476 if buffer[2] then | |
| 477 data = t_concat(data); | |
| 478 else | |
| 479 data = buffer[1] or ""; | |
| 480 end | |
| 481 end | |
| 475 local ok, err, partial = self.conn:send(data); | 482 local ok, err, partial = self.conn:send(data); |
| 476 if ok then | 483 if ok then |
| 477 self:set(nil, false); | 484 self:set(nil, false); |
| 478 if cfg.keep_buffers then | 485 if cfg.keep_buffers and type(buffer) == "table" then |
| 479 for i = #buffer, 1, -1 do | 486 for i = #buffer, 1, -1 do |
| 480 buffer[i] = nil; | 487 buffer[i] = nil; |
| 481 end | 488 end |
| 482 else | 489 else |
| 483 self.writebuffer = nil; | 490 self.writebuffer = nil; |
| 485 self:setwritetimeout(false); | 492 self:setwritetimeout(false); |
| 486 self:ondrain(); -- Be aware of writes in ondrain | 493 self:ondrain(); -- Be aware of writes in ondrain |
| 487 return ok; | 494 return ok; |
| 488 elseif partial then | 495 elseif partial then |
| 489 self:debug("Sent %d out of %d buffered bytes", partial, #data); | 496 self:debug("Sent %d out of %d buffered bytes", partial, #data); |
| 490 if cfg.keep_buffers then | 497 if cfg.keep_buffers and type(buffer) == "table" then |
| 491 buffer[1] = data:sub(partial+1); | 498 buffer[1] = data:sub(partial+1); |
| 492 for i = #buffer, 2, -1 do | 499 for i = #buffer, 2, -1 do |
| 493 buffer[i] = nil; | 500 buffer[i] = nil; |
| 494 end | 501 end |
| 495 else | 502 else |
| 496 data.writebuffer = { data:sub(partial+1) }; | 503 data.writebuffer = data:sub(partial+1); |
| 497 end | 504 end |
| 498 self:set(nil, true); | 505 self:set(nil, true); |
| 499 self:setwritetimeout(); | 506 self:setwritetimeout(); |
| 500 end | 507 end |
| 501 if err == "wantwrite" or err == "timeout" then | 508 if err == "wantwrite" or err == "timeout" then |
| 515 end | 522 end |
| 516 | 523 |
| 517 -- Add data to write buffer and set flag for wanting to write | 524 -- Add data to write buffer and set flag for wanting to write |
| 518 function interface:write(data) | 525 function interface:write(data) |
| 519 local buffer = self.writebuffer; | 526 local buffer = self.writebuffer; |
| 520 if buffer then | 527 if type(buffer) == "table" then |
| 521 t_insert(buffer, data); | 528 t_insert(buffer, data); |
| 522 else | 529 elseif type(buffer) == "string" then |
| 523 self:noise("Allocating buffer!") | 530 self:noise("Allocating buffer!") |
| 524 self.writebuffer = { data }; | 531 self.writebuffer = { buffer, data }; |
| 532 elseif buffer == nil then | |
| 533 self.writebuffer = data; | |
| 525 end | 534 end |
| 526 if not self._write_lock then | 535 if not self._write_lock then |
| 527 if cfg.opportunistic_writes and not self._opportunistic_write then | 536 if cfg.opportunistic_writes and not self._opportunistic_write then |
| 528 self._opportunistic_write = true; | 537 self._opportunistic_write = true; |
| 529 local ret, err = self:onwritable(); | 538 local ret, err = self:onwritable(); |
| 537 end | 546 end |
| 538 interface.send = interface.write; | 547 interface.send = interface.write; |
| 539 | 548 |
| 540 -- Close, possibly after writing is done | 549 -- Close, possibly after writing is done |
| 541 function interface:close() | 550 function interface:close() |
| 542 if self.writebuffer and self.writebuffer[1] then | 551 if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then |
| 543 self:set(false, true); -- Flush final buffer contents | 552 self:set(false, true); -- Flush final buffer contents |
| 544 self:setwritetimeout(); | 553 self:setwritetimeout(); |
| 545 self.write, self.send = noop, noop; -- No more writing | 554 self.write, self.send = noop, noop; -- No more writing |
| 546 self:debug("Close after writing remaining buffered data"); | 555 self:debug("Close after writing remaining buffered data"); |
| 547 self.ondrain = interface.close; | 556 self.ondrain = interface.close; |
| 576 end | 585 end |
| 577 | 586 |
| 578 function interface:starttls(tls_ctx) | 587 function interface:starttls(tls_ctx) |
| 579 if tls_ctx then self.tls_ctx = tls_ctx; end | 588 if tls_ctx then self.tls_ctx = tls_ctx; end |
| 580 self.starttls = false; | 589 self.starttls = false; |
| 581 if self.writebuffer and self.writebuffer[1] then | 590 if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then |
| 582 self:debug("Start TLS after write"); | 591 self:debug("Start TLS after write"); |
| 583 self.ondrain = interface.starttls; | 592 self.ondrain = interface.starttls; |
| 584 self:set(nil, true); -- make sure wantwrite is set | 593 self:set(nil, true); -- make sure wantwrite is set |
| 585 else | 594 else |
| 586 if self.ondrain == interface.starttls then | 595 if self.ondrain == interface.starttls then |
| 685 conn = client; | 694 conn = client; |
| 686 _server = server; | 695 _server = server; |
| 687 created = realtime(); | 696 created = realtime(); |
| 688 listeners = listeners; | 697 listeners = listeners; |
| 689 read_size = read_size or (server and server.read_size); | 698 read_size = read_size or (server and server.read_size); |
| 690 writebuffer = {}; | 699 writebuffer = nil; |
| 691 tls_ctx = tls_ctx or (server and server.tls_ctx); | 700 tls_ctx = tls_ctx or (server and server.tls_ctx); |
| 692 tls_direct = server and server.tls_direct; | 701 tls_direct = server and server.tls_direct; |
| 693 id = conn_id; | 702 id = conn_id; |
| 694 log = logger.init(conn_id); | 703 log = logger.init(conn_id); |
| 695 extra = extra; | 704 extra = extra; |
| 809 if not self._write_lock then | 818 if not self._write_lock then |
| 810 return | 819 return |
| 811 end | 820 end |
| 812 self:noise("Resume writes"); | 821 self:noise("Resume writes"); |
| 813 self._write_lock = nil; | 822 self._write_lock = nil; |
| 814 if self.writebuffer[1] then | 823 if self.writebuffer and (self.writebuffer[1] or type(self.writebuffer) == "string") then |
| 815 self:setwritetimeout(); | 824 self:setwritetimeout(); |
| 816 self:set(nil, true); | 825 self:set(nil, true); |
| 817 end | 826 end |
| 818 end | 827 end |
| 819 | 828 |
