diff options
author | Jean Boussier <[email protected]> | 2024-12-21 11:27:09 +0100 |
---|---|---|
committer | git <[email protected]> | 2025-01-14 11:54:47 +0000 |
commit | 2f5d31d38ad6918410da1c41936e043f47725d4f (patch) | |
tree | dd7dbddff68ed5983b00782996cf8aecd4fa8218 /ext/openssl/lib | |
parent | ccb4ba45ed0439764fc44a40469e396187d83a71 (diff) |
[ruby/openssl] Reduce OpenSSL::Buffering#do_write overhead
[Bug #20972]
The `rb_str_new_freeze` was added in https://github.com/ruby/openssl/issues/452
to better handle concurrent use of a Socket, but SSL sockets can't be used
concurrently AFAIK, so we might as well just error cleanly.
By using `rb_str_locktmp` we can ensure attempts at concurrent write
will raise an error, be we avoid causing a copy of the bytes.
We also use the newer `String#append_as_bytes` method when available
to save on some more copies.
https://github.com/ruby/openssl/commit/0d8c17aa85
Co-Authored-By: [email protected]
Diffstat (limited to 'ext/openssl/lib')
-rw-r--r-- | ext/openssl/lib/openssl/buffering.rb | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index 85f593af0f..ceb2efb733 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -24,25 +24,21 @@ module OpenSSL::Buffering # A buffer which will retain binary encoding. class Buffer < String - BINARY = Encoding::BINARY - - def initialize - super - - force_encoding(BINARY) - end + unless String.method_defined?(:append_as_bytes) + alias_method :_append, :<< + def append_as_bytes(string) + if string.encoding == Encoding::BINARY + _append(string) + else + _append(string.b) + end - def << string - if string.encoding == BINARY - super(string) - else - super(string.b) + self end - - return self end - alias concat << + alias_method :concat, :append_as_bytes + alias_method :<<, :append_as_bytes end ## @@ -352,22 +348,32 @@ module OpenSSL::Buffering def do_write(s) @wbuffer = Buffer.new unless defined? @wbuffer - @wbuffer << s - @wbuffer.force_encoding(Encoding::BINARY) + @wbuffer.append_as_bytes(s) + @sync ||= false - buffer_size = @wbuffer.size + buffer_size = @wbuffer.bytesize if @sync or buffer_size > BLOCK_SIZE nwrote = 0 begin while nwrote < buffer_size do begin - nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote]) + chunk = if nwrote > 0 + @wbuffer.byteslice(nwrote, @wbuffer.bytesize) + else + @wbuffer + end + + nwrote += syswrite(chunk) rescue Errno::EAGAIN retry end end ensure - @wbuffer[0, nwrote] = "" + if nwrote < @wbuffer.bytesize + @wbuffer[0, nwrote] = "" + else + @wbuffer.clear + end end end end |