tls_wrap: use writev when possible
authorFedor Indutny <fedor.indutny@gmail.com>
Wed, 27 Nov 2013 22:49:30 +0000 (02:49 +0400)
committerFedor Indutny <fedor.indutny@gmail.com>
Fri, 6 Dec 2013 23:47:57 +0000 (03:47 +0400)
Try writing multiple chunks from NodeBIO if possible.

src/node_crypto_bio.cc
src/node_crypto_bio.h
src/tls_wrap.cc
src/tls_wrap.h

index 05a4b5f..84dc42b 100644 (file)
@@ -96,6 +96,33 @@ char* NodeBIO::Peek(size_t* size) {
 }
 
 
+size_t NodeBIO::PeekMultiple(char** out, size_t* size, size_t* count) {
+  Buffer* pos = read_head_;
+  size_t max = *count;
+  size_t total = 0;
+
+  size_t i;
+  for (i = 0; i < max; i++) {
+    size[i] = pos->write_pos_ - pos->read_pos_;
+    total += size[i];
+    out[i] = pos->data_ + pos->read_pos_;
+
+    /* Don't get past write head */
+    if (pos == write_head_)
+      break;
+    else
+      pos = pos->next_;
+  }
+
+  if (i == max)
+    *count = i;
+  else
+    *count = i + 1;
+
+  return total;
+}
+
+
 int NodeBIO::Write(BIO* bio, const char* data, int len) {
   BIO_clear_retry_flags(bio);
 
index 615fea9..0b9b344 100644 (file)
@@ -55,6 +55,10 @@ class NodeBIO {
   // contiguous data available to read
   char* Peek(size_t* size);
 
+  // Return pointers and sizes of multiple internal data chunks available for
+  // reading
+  size_t PeekMultiple(char** out, size_t* size, size_t* count);
+
   // Find first appearance of `delim` in buffer or `limit` if `delim`
   // wasn't found.
   size_t IndexOf(char delim, size_t limit);
index 6ceb861..b7bce94 100644 (file)
@@ -263,12 +263,17 @@ void TLSCallbacks::EncOut() {
     return;
   }
 
-  char* data = NodeBIO::FromBIO(enc_out_)->Peek(&write_size_);
-  assert(write_size_ != 0);
+  char* data[kSimultaneousBufferCount];
+  size_t size[ARRAY_SIZE(data)];
+  size_t count = ARRAY_SIZE(data);
+  write_size_ = NodeBIO::FromBIO(enc_out_)->PeekMultiple(data, size, &count);
+  assert(write_size_ != 0 && count != 0);
 
   write_req_.data = this;
-  uv_buf_t buf = uv_buf_init(data, write_size_);
-  int r = uv_write(&write_req_, wrap()->stream(), &buf, 1, EncOutCb);
+  uv_buf_t buf[ARRAY_SIZE(data)];
+  for (size_t i = 0; i < count; i++)
+    buf[i] = uv_buf_init(data[i], size[i]);
+  int r = uv_write(&write_req_, wrap()->stream(), buf, count, EncOutCb);
 
   // Ignore errors, this should be already handled in js
   if (!r) {
index 924a724..a5090cb 100644 (file)
@@ -68,6 +68,9 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
  protected:
   static const int kClearOutChunkSize = 1024;
 
+  // Maximum number of buffers passed to uv_write()
+  static const int kSimultaneousBufferCount = 10;
+
   // Write callback queue's item
   class WriteItem {
    public: