From 03747f69fba646dc9902519c1736d5f4f267ef7b Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 28 Nov 2013 02:49:30 +0400 Subject: [PATCH] tls_wrap: use writev when possible Try writing multiple chunks from NodeBIO if possible. --- src/node_crypto_bio.cc | 27 +++++++++++++++++++++++++++ src/node_crypto_bio.h | 4 ++++ src/tls_wrap.cc | 13 +++++++++---- src/tls_wrap.h | 3 +++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/node_crypto_bio.cc b/src/node_crypto_bio.cc index 05a4b5f..84dc42b 100644 --- a/src/node_crypto_bio.cc +++ b/src/node_crypto_bio.cc @@ -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); diff --git a/src/node_crypto_bio.h b/src/node_crypto_bio.h index 615fea9..0b9b344 100644 --- a/src/node_crypto_bio.h +++ b/src/node_crypto_bio.h @@ -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); diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 6ceb861..b7bce94 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -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) { diff --git a/src/tls_wrap.h b/src/tls_wrap.h index 924a724..a5090cb 100644 --- a/src/tls_wrap.h +++ b/src/tls_wrap.h @@ -68,6 +68,9 @@ class TLSCallbacks : public crypto::SSLWrap, 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: -- 2.7.4