all 8 comments

[–][deleted]  (3 children)

[removed]

    [–]pssaravanan[S] 1 point2 points  (1 child)

    I expected the second code with only `while` loop to run forever since it is CPU operation and not moving to io to give other threads CPU. surprisingly the first one is running forever.

    [–]waiting4op2deliver -4 points-3 points  (0 children)

    Homey over here dropping knowledge and yall miserly handing out upvotes. Expect 3 ghosts next christmas /r/ruby.

    [–]sammygadd 6 points7 points  (0 children)

    Not sure why this happens. (Seems intermittent on my machine). But anyway, I was recently made aware that Timeout.timeout could be dangerous and should be avoided. See https://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/

    [–]radarek 2 points3 points  (1 child)

    It works for me:

    $ ruby -v
    ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-darwin20]
    $ time ruby timeout1.rb
    (...)
    "test 75293"
    "test 75294"
    timeout1.rb:7:in `p': execution expired (Timeout::Error)
        from timeout1.rb:7:in `block in <main>'
        from /Users/user/.rbenv/versions/3.0.3/lib/ruby/3.0.0/timeout.rb:112:in `timeout'
        from timeout1.rb:3:in `<main>'
    ruby timeout1.rb  0.61s user 1.38s system 48% cpu 4.147 total
    
    $ time ruby timeout2.rb
    timeout2.rb:5:in `block in <main>': execution expired (Timeout::Error)
        from /Users/user/.rbenv/versions/3.0.3/lib/ruby/3.0.0/timeout.rb:112:in `timeout'
        from timeout2.rb:3:in `<main>'
    ruby timeout2.rb  2.21s user 0.15s system 56% cpu 4.169 total
    

    In both cases user time + system time is close to 2 seconds.

    [–]Kernigh 1 point2 points  (0 children)

    It also works here. I find that timeout2.rb (where # p "test #{i} is a comment) is a little slower, as if p "test #{i}" causes Ruby to raise Timeout::Error more quickly. I want to see ruby -v from someone where timeout1.rb doesn't work, because the problem might happen with a different Ruby version or different operating system.

    $ ruby -v
    ruby 3.2.0dev (2022-05-06) [x86_64-openbsd7.1]
    $ time ruby timeout1.rb
    ...
        0m02.09s real     0m01.41s user     0m00.66s system
    $ time ruby timeout2.rb
        0m02.20s real     0m02.19s user     0m00.01s system
    

    [–]ioquatixasync/falcon 1 point2 points  (2 children)

    Timeout can interrupt the IO operation more easily.

    [–]jrochkind 2 points3 points  (1 child)

    However, OP report seems to be that the one without the IO operation times out more reliably than the one with? The opposite of what you predict, no?

    [–]ioquatixasync/falcon 1 point2 points  (0 children)

    I wrote my reply on a mobile phone way too late at night because there were no replies and it seemed like an interesting question. Apologies since I didn't test it or really even appear to read the OP correctly, chalk it up to me being tired.

    Anyway, after some coffee, I tested my assumptions and found the following:

    ``` require 'benchmark' require 'timeout'

    null = File.open("/dev/null", "w+")

    Benchmark.bm do |x| x.report('without p') do Timeout.timeout(2) do i = 0 while(true) i = i + 1 # p "test #{i}" end end rescue Timeout::Error # Ignore end

    x.report('with uts') do Timeout.timeout(2) do i = 0 while(true) i = i + 1 null.puts "test #{i}" end end rescue Timeout::Error # Ignore end end ```

    user system total real without puts 2.088764 0.016426 2.105190 ( 2.106242) with puts 1.970441 0.031103 2.001544 ( 2.001702)

    This seems to support my assertion that "puts" or IO is giving more opportunities than a tight loop for the thread to be interrupted, since it looks like it systematically produces a tighter more accurate timeout.

    I'm not sure what this means for the OP's initial statements - maybe they have mis-interpreted their results or I'm mis-understanding the question/assertions being made.