From 97357e41f09abffe9c226166590a0853ba50ac45 Mon Sep 17 00:00:00 2001 From: Kevin Hughes Date: Tue, 10 Aug 2021 15:28:51 -0400 Subject: [PATCH] preallocate a buffer for reading from a socket --- .rubocop.yml | 3 +++ lib/redis/connection/ruby.rb | 30 ++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 96fb535ce..36560bcef 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -106,6 +106,9 @@ Lint/EndAlignment: Layout/ElseAlignment: Enabled: false +Layout/RescueEnsureAlignment: + Enabled: false + Naming/HeredocDelimiterNaming: Enabled: false diff --git a/lib/redis/connection/ruby.rb b/lib/redis/connection/ruby.rb index 7ef5ca9fa..995018ec7 100644 --- a/lib/redis/connection/ruby.rb +++ b/lib/redis/connection/ruby.rb @@ -32,12 +32,30 @@ def write_timeout=(timeout) @write_timeout = (timeout if timeout && timeout > 0) end - def read(nbytes) - result = @buffer.slice!(0, nbytes) + string_capacity_support = begin + String.new(capacity: 0) + true # Ruby 2.4+ + rescue ArgumentError + false # Ruby 2.3 + end + + if string_capacity_support + def read(nbytes) + result = @buffer.slice!(0, nbytes) - result << _read_from_socket(nbytes - result.bytesize) while result.bytesize < nbytes + buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT) + result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes - result + result + end + else + def read(nbytes) + result = @buffer.slice!(0, nbytes) + + result << _read_from_socket(nbytes - result.bytesize, "".b) while result.bytesize < nbytes + + result + end end def gets @@ -48,9 +66,9 @@ def gets @buffer.slice!(0, crlf + CRLF.bytesize) end - def _read_from_socket(nbytes) + def _read_from_socket(nbytes, buffer = nil) loop do - case chunk = read_nonblock(nbytes, exception: false) + case chunk = read_nonblock(nbytes, buffer, exception: false) when :wait_readable unless wait_readable(@timeout) raise Redis::TimeoutError