【问题标题】:Why does `File.write` slow down sometimes?为什么`File.write`有时会变慢?
【发布时间】:2019-03-29 23:18:55
【问题描述】:

这是我的代码:

start = Time.now
File.write('/tmp/a.txt', 'Hello, world!')
puts "Saved in #{Time.now - start}"

在某些情况下,我会在日志中看到:

Saved in 0.001
Saved in 0.002
Saved in 0.245
Saved in 0.002

为什么偶尔会出现这样的峰值?那会是什么?我没有在任何地方使用flock。我的怀疑是某些库已经覆盖了 File.write() 方法并在那里添加了一些锁定/同步。有可能吗?

更新:Dir.new() 似乎会定期访问该目录,但会阻止对该目录的访问。

【问题讨论】:

标签: ruby io


【解决方案1】:

我不确定,但我会很惊讶那些提到的时间不是来自 Ruby,而是来自你的底层操作系统(我猜是 Linux)。

我用 Python 写了一个和你类似的脚本,我可以看到和你一样的差异。

我看它的系统调用使用:

sudo strace -T -e trace=open,close,write -p <my_process_pid>

至少对于open 系统调用,我还可以看到一些调用比其他调用长 100 次。

【讨论】:

    【解决方案2】:

    好像Dir.new()在应用程序的另一个地方完全锁定了整个目录,不允许File.write()快速工作。这是重现问题的测试(使用threads gem):

    require 'tmpdir'
    require 'threads'
    Dir.mktmpdir do |dir|
      file = File.join(dir, 'hey.txt')
      Thread.start do
        loop do
          Dir.new(dir)
        end
      end
      Threads.new(100).assert do
        start = Time.now
        File.open(file, 'w+') do |f|
          f.write('test')
        end
        puts("Saved in #{Time.now - start}")
        sleep 1
      end
    end
    

    这个会运行缓慢。但是,如果你用这个替换Dir.new,一切都会再次快速进行:

    `ls #{dir}`.split(' ')
    

    Ruby 错误?我不知道。

    顺便说一句,Dir.glob() 也是如此 - 它也很慢。

    【讨论】: