【问题标题】:What is the point of Fibers in Ruby?Ruby 中的 Fibers 有什么意义?
【发布时间】:2013-05-15 12:35:35
【问题描述】:

我不明白下面是怎么回事:

counts = Hash.new(0)

File.foreach("testfile") do |line|
  line.scan(/\w+/) do |word|
    word = word.downcase
    counts[word] += 1
  end
end

counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}

比:

words = Fiber.new do
  File.foreach("testfile") do |line|
    line.scan(/\w+/) do |word|
      Fiber.yield word.downcase
    end
  end
end

counts = Hash.new(0)

while word = words.resume
  counts[word] += 1
end

counts.keys.sort.each {|k| print "#{k}:#{counts[k]} "}

【问题讨论】:

    标签: ruby-on-rails ruby multithreading fibers


    【解决方案1】:

    Fiber 是一种暂停和恢复任意代码块的方法。像这样的示例并不是一个很好的用例,因为与传统的逐行读取和处理方式相比,它没有提供任何真正的优势。

    在这个特定的例子中,如果你想让它变得更好,你可以编写一个枚举器风格的接口,这样你就可以这样写:

    words = WordsReader.new("testfile")
    
    words.each do |word|
      # ...
    end
    

    Fibers 变得重要的地方在于编写异步代码。例如,在EventMachine 环境中,您需要能够发出异步调用、暂停代码块并在收到响应时恢复它。

    这最终看起来像这样:

    async_call(argument1, argument2) do |response_1|
      if (response_1.ok?)
        async_call(argument3, argument4) do |response_2|
          if (response_2.ok?)
            async_call(argument5, argument6) do |response_3|
              if (response_3.ok?)
                do_something(response_1, response_2, response_3)
              else
                panic_and_fail!
              end
            end
          else
            panic_and_fail!
          end
        end
      else
        panic_and_fail!
      end
    end
    

    这种嵌套、嵌套和重新嵌套的调用结构被松散地称为“回调地狱”,因为一旦你的逻辑变得不平凡,它就会变得非常难以管理。使这种结构变平的一种方法是使用纤维。一个适当的 Fiber-ized 等效项是:

    begin
      response_1 = fiber_call(argument1, argument2)
      response_2 = fiber_call(argument3, argument4)
      response_3 = fiber_call(argument5, argument6)
    
      do_something(response_1, response_2, response_3)
    
    rescue NotOkay
      panic_and_fail!
    end
    

    Fibers 可以利用异常,而回调类型的代码则不能。如您在此处所见,异常在有效使用时可以大大简化代码块。不是在每个响应上测试ok?,而是预计调用将引发NotOkay 类型的异常。

    回调不能可靠地抛出异常,因为回调发生时调用的发起者已经超出范围。这是使用回调进行异步编程的基本限制。 Fiber 驱动的代码维护一个适当的调用堆栈,它只是按原样暂停和恢复,因此异常通过调用者适当地级联。

    我发现 Fiber 既易于理解又很难正确应用。大多数情况下,您不必直接使用它们,而是使用使用它们的库。编写“光纤感知”代码与编写“线程安全”代码没有什么不同。做对可能很棘手。

    【讨论】:

    • 你在 17 分钟内写完所有这些?
    • 显然如此。不知道我被计时了!
    • 哇 Tadman,我非常感谢您为向我和任何可能遇到它的人解释这一点所做的深入。对此,我真的非常感激。来自加拿大同胞的你好! :)
    • Fiber 是神秘的,而且人们对它们了解甚少,尽管它们已经在 Ruby 中使用了大约五年。我只是希望有更好的文档来说明如何有效地使用它们,所以我只是在这里做我的一小部分。这里有很多加拿大人,所以欢迎!
    猜你喜欢
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2018-12-21
    • 2016-02-15
    • 2016-09-17
    相关资源
    最近更新 更多