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