Software /
code /
prosody
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 |
parent | 11696:917eca7be82b |
child | 11698: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 |