user3756502 user3756502 - 1 month ago 18
Linux Question

Ruby sysread IO much too slow

I have a command like this:

STDIN.sysread(1000,input)


(
input
is a string that receives the input.)

But if it reads more than 100 characters it takes more than 0.1 seconds.

I tried it with alternatives such as
partialread
and nonblocking reading and
read
, but I didn't find a faster alternative so far.

Do you know any faster possibility to simply read this sh***?

Many thanks!

Update:

t=Time.now
STDIN.sysread(1000,input)
stdin_time=Time.now-t


stdin_time
is bigger than 0.1
if input.length > 100


I read mouse movements from terminal within X-Window.

Does sysread wait for more input than available before it finishes execution?

Answer

There is probably something odd in your benchmarking setup. What comes to mind first is that your sender might not write fast enough.

The following benchmark (using benchmark-ips) resulted in approximately one read every 1.3 micro-seconds on my 4-years-old Macbook on Ruby 2.2.5.

This benchmark contains additional code to verify that we are reading exactly 1000-character strings. This makes the benchmark almost 50% slower, but still much faster than you claim.

require 'benchmark/ips'

sysread_1k_strings = 0
read_1k_strings = 0

Benchmark.ips do |x|
  input = ''

  x.warmup = 0

  x.report('sysread') {
    STDIN.sysread(1000, input)
    sysread_1k_strings += 1 if input.length == 1000
  }

  x.report('read') {
    STDIN.read(1000, input)
    read_1k_strings += 1 if input.length == 1000
  }

end

puts "Comparison --------------------------------------"
puts "sysread".rjust(20) + "#{sysread_1k_strings.to_s.rjust(11)} 1000 byte strings read"
puts "read".rjust(20) + "#{read_1k_strings.to_s.rjust(11)} 1000 byte strings read"

When reading from /dev/zero this resulted in the following benchmark result:

$ ruby benchmark.rb < /dev/zero
Warming up --------------------------------------
             sysread     1.000  i/100ms
                read     1.000  i/100ms
Calculating -------------------------------------
             sysread    210.517k (±13.5%) i/s -    915.780k in   4.529414s
                read    475.210k (±10.4%) i/s -      1.956M in   4.209967s
Comparison --------------------------------------
             sysread     915780 1000 byte strings read
                read    1955737 1000 byte strings read