summaryrefslogtreecommitdiff
path: root/ext/openssl/lib
diff options
context:
space:
mode:
authorJaymz Julian <jaymzjulian@meta.com>2024-02-05 15:00:47 -0800
committerKazuki Yamaguchi <k@rhe.jp>2024-05-02 16:24:36 +0900
commitd39993a4ce15004d98a450dd71bb804fd0e37182 (patch)
tree4300f4d744ec7062fccafbd34921998dac434a1e /ext/openssl/lib
parentf5af620c611bf62d2b29111a0347f306c1f38644 (diff)
[ruby/openssl] Fix performance regression in do_write(s)
This causes significant performance issues when using large (>10meg) writes Fix by adjusting the buffer write function to clear the buffer once, rather than piece by piece, avoiding a case where a large write (in our case, around 70mbytes) will consume 100% of CPU. This takes a webrick GET request via SSL from around 200kbyts/sec and consuming 100% of a core, to line speed on gigabit ethernet and 6% cpu utlization. https://github.com/ruby/openssl/commit/d4389b425d
Diffstat (limited to 'ext/openssl/lib')
-rw-r--r--ext/openssl/lib/openssl/buffering.rb17
1 files changed, 11 insertions, 6 deletions
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 68aa7bc970..216c51e3be 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -349,13 +349,18 @@ module OpenSSL::Buffering
@wbuffer << s
@wbuffer.force_encoding(Encoding::BINARY)
@sync ||= false
- if @sync or @wbuffer.size > BLOCK_SIZE
- until @wbuffer.empty?
- begin
- nwrote = syswrite(@wbuffer)
- rescue Errno::EAGAIN
- retry
+ buffer_size = @wbuffer.size
+ if @sync or buffer_size > BLOCK_SIZE
+ nwrote = 0
+ begin
+ while nwrote < buffer_size do
+ begin
+ nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote])
+ rescue Errno::EAGAIN
+ retry
+ end
end
+ ensure
@wbuffer[0, nwrote] = ""
end
end