From 44baf906e73c13577186e3135be4356b33b8be43 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 2 Jan 2019 20:37:38 +0000 Subject: use sleepy_penguin 3.5+ for splice and tee support Eliminate loading of the io_splice RubyGem to reduce memory overhead. Extra DSOs are wasteful and io_splice is being phased oiut for sleepy_penguin, which encapsulates more Linux-specific functionality anyways. cf. https://udrepper.livejournal.com/8790.html --- lib/dtas/buffer.rb | 4 +++- lib/dtas/buffer/read_write.rb | 2 +- lib/dtas/buffer/splice.rb | 20 +++++++++++--------- lib/dtas/pipe.rb | 13 ++++++++----- 4 files changed, 23 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/dtas/buffer.rb b/lib/dtas/buffer.rb index 6f43dfa..c3d8ee2 100644 --- a/lib/dtas/buffer.rb +++ b/lib/dtas/buffer.rb @@ -8,7 +8,9 @@ require_relative '../dtas' class DTAS::Buffer # :nodoc: begin raise LoadError, "no splice with _DTAS_POSIX" if ENV["_DTAS_POSIX"] - require 'io/splice' # splice is only in Linux for now... + require 'sleepy_penguin' # splice is only in Linux for now... + SleepyPenguin.respond_to?(:splice) or + raise LoadError, 'sleepy_penguin 3.5+ required for splice', [] require_relative 'buffer/splice' include DTAS::Buffer::Splice rescue LoadError diff --git a/lib/dtas/buffer/read_write.rb b/lib/dtas/buffer/read_write.rb index 5845309..06947a5 100644 --- a/lib/dtas/buffer/read_write.rb +++ b/lib/dtas/buffer/read_write.rb @@ -7,7 +7,7 @@ require_relative '../pipe' require_relative '../nonblock' # compatibility code for systems lacking "splice" support via the -# "io-splice" RubyGem. Used only by -player +# "sleepy_penguin" 3.5+ RubyGem. Used only by -player module DTAS::Buffer::ReadWrite # :nodoc: MAX_AT_ONCE = 512 # min PIPE_BUF value in POSIX attr_accessor :buffer_size diff --git a/lib/dtas/buffer/splice.rb b/lib/dtas/buffer/splice.rb index 1cb0fbc..cd00bbb 100644 --- a/lib/dtas/buffer/splice.rb +++ b/lib/dtas/buffer/splice.rb @@ -2,15 +2,17 @@ # License: GPL-3.0+ # frozen_string_literal: true require 'io/nonblock' -require 'io/splice' +require 'sleepy_penguin' require_relative '../../dtas' require_relative '../pipe' -# Used by -player on Linux systems with the "io-splice" RubyGem installed +# Used by -player on Linux systems with the "sleepy_penguin" RubyGem installed module DTAS::Buffer::Splice # :nodoc: MAX_AT_ONCE = 4096 # page size in Linux MAX_AT_ONCE_1 = 65536 - F_MOVE = IO::Splice::F_MOVE + F_MOVE = SleepyPenguin::F_MOVE + F_NONBLOCK = SleepyPenguin::F_NONBLOCK + TRY = { exception: false }.freeze def buffer_size @to_io.pipe_size @@ -24,13 +26,13 @@ module DTAS::Buffer::Splice # :nodoc: # be sure to only call this with nil when all writers to @wr are done def discard(bytes) - IO.splice(@to_io, nil, DTAS.null, nil, bytes) + SleepyPenguin.splice(@to_io, DTAS.null, bytes) end def broadcast_one(targets, limit = nil) # single output is always non-blocking limit ||= MAX_AT_ONCE_1 - s = IO.trysplice(@to_io, nil, targets[0], nil, limit, F_MOVE) + s = SleepyPenguin.splice(@to_io, targets[0], limit, F_MOVE, TRY) if Symbol === s targets # our one and only target blocked on write else @@ -46,7 +48,7 @@ module DTAS::Buffer::Splice # :nodoc: def __tee_in_full(src, dst, bytes) rv = 0 while bytes > 0 - s = IO.tee(src, dst, bytes) + s = SleepyPenguin.tee(src, dst, bytes) bytes -= s rv += s end @@ -56,7 +58,7 @@ module DTAS::Buffer::Splice # :nodoc: def __splice_in_full(src, dst, bytes, flags) rv = 0 while bytes > 0 - s = IO.splice(src, nil, dst, nil, bytes, flags) + s = SleepyPenguin.splice(src, dst, bytes, flags) rv += s bytes -= s end @@ -69,7 +71,7 @@ module DTAS::Buffer::Splice # :nodoc: targets.delete_if do |dst| begin t = (dst.nonblock? || most_teed == 0) ? - IO.trytee(@to_io, dst, chunk_size) : + SleepyPenguin.tee(@to_io, dst, chunk_size, F_NONBLOCK, TRY) : __tee_in_full(@to_io, dst, chunk_size) if Integer === t if t > most_teed @@ -117,7 +119,7 @@ module DTAS::Buffer::Splice # :nodoc: begin targets << last if last.nonblock? || most_teed == 0 - s = IO.trysplice(@to_io, nil, last, nil, bytes, F_MOVE) + s = SleepyPenguin.splice(@to_io, last, bytes, F_MOVE|F_NONBLOCK, TRY) if Symbol === s blocked << last diff --git a/lib/dtas/pipe.rb b/lib/dtas/pipe.rb index f9d5149..97cbd71 100644 --- a/lib/dtas/pipe.rb +++ b/lib/dtas/pipe.rb @@ -2,7 +2,7 @@ # License: GPL-3.0+ # frozen_string_literal: true begin - require 'io/splice' + require 'sleepy_penguin' rescue LoadError end require_relative '../dtas' @@ -20,12 +20,15 @@ class DTAS::Pipe < DTAS::Nonblock # :nodoc: rv end - # create no-op methods for non-Linux - unless method_defined?(:pipe_size=) - def pipe_size=(_) - end + def pipe_size=(nr) + defined?(SleepyPenguin::F_SETPIPE_SZ) and + fcntl(SleepyPenguin::F_SETPIPE_SZ, nr) end + def pipe_size + fcntl(SleepyPenguin::F_GETPIPE_SZ) + end if defined?(SleepyPenguin::F_GETPIPE_SZ) + # avoid syscall, we never change IO#nonblock= directly def nonblock? false -- cgit v1.2.3-24-ge0c7