与光纤的简单并行性?
Simple parallelism with Fibers?
我正在尝试使用两个光纤验证基本 yield/resume 模式。但是, yield/resume 机制似乎不起作用。我尝试了一些变体,但找不到我的错误。
预期的事件顺序:
- 启动线程(时间 0)
- 等到第一个returns(时间+2秒)
- 等到第二个returns(时间+2秒)
- 完成(时间 > +3 秒)
尝试#1
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
fib1 = Fiber.current
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
fib1.resume(1)
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
fib2 = Fiber.current
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
fib2.resume(2)
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
sleep 1
puts "Done @ #{Time.now}."
这导致:
Waiting @ 2016-06-01 06:15:52 -0700.
Fiber1 starting @ 2016-06-01 06:15:52 -0700.
f1 back @ 2016-06-01 06:15:52 -0700 - .
Fiber2 starting @ 2016-06-01 06:15:52 -0700.
f2 back @ 2016-06-01 06:15:52 -0700 - .
Done @ 2016-06-01 06:15:53 -0700.
添加第二个 resume
会导致 FiberError。
试试#2
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
1
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
2
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
sleep 1
puts "Done @ #{Time.now}."
这导致:
Waiting @ 2016-06-01 10:53:17 -0700.
Fiber1 starting @ 2016-06-01 10:53:17 -0700.
f1 back @ 2016-06-01 10:53:17 -0700 - .
Fiber2 starting @ 2016-06-01 10:53:17 -0700.
f2 back @ 2016-06-01 10:53:17 -0700 - .
Done @ 2016-06-01 10:53:18 -0700.
在这两种情况下,start/end时间相同,结果未返回。
Fiber 本身不会让你实现并行性,至少在不使用某种回调机制(例如 eventmachine 框架)的情况下不会。
你写的只是试图在代码块之间交错同步执行。你没有得到预期顺序的原因是因为当你模拟开球时,你从未在屈服后恢复纤维。
您可能会发现以下 post 有用,尤其是末尾的示例:
http://schmurfy.github.io/2011/09/25/on_fibers_and_threads.html
另一个显示纤程相互转移控制的示例:
https://gist.github.com/aprescott/971008
这应该会给你预期的结果:
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
1
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
2
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
# Resume right after the yield in the fiber block and
# execute until it encounters another yield or the block ends.
puts "Resuming f1"
f1.resume
puts "Resuming f2"
f2.resume
sleep 1
puts "Done @ #{Time.now}."
输出:
Waiting @ 2016-06-05 00:35:29 -0700.
Fiber1 starting @ 2016-06-05 00:35:29 -0700.
f1 back @ 2016-06-05 00:35:29 -0700 - .
Fiber2 starting @ 2016-06-05 00:35:29 -0700.
f2 back @ 2016-06-05 00:35:29 -0700 - .
Resuming f1
Fiber1 done @ 2016-06-05 00:35:31 -0700.
Resuming f2
Fiber2 done @ 2016-06-05 00:35:33 -0700.
Done @ 2016-06-05 00:35:34 -0700.
我正在尝试使用两个光纤验证基本 yield/resume 模式。但是, yield/resume 机制似乎不起作用。我尝试了一些变体,但找不到我的错误。
预期的事件顺序:
- 启动线程(时间 0)
- 等到第一个returns(时间+2秒)
- 等到第二个returns(时间+2秒)
- 完成(时间 > +3 秒)
尝试#1
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
fib1 = Fiber.current
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
fib1.resume(1)
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
fib2 = Fiber.current
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
fib2.resume(2)
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
sleep 1
puts "Done @ #{Time.now}."
这导致:
Waiting @ 2016-06-01 06:15:52 -0700.
Fiber1 starting @ 2016-06-01 06:15:52 -0700.
f1 back @ 2016-06-01 06:15:52 -0700 - .
Fiber2 starting @ 2016-06-01 06:15:52 -0700.
f2 back @ 2016-06-01 06:15:52 -0700 - .
Done @ 2016-06-01 06:15:53 -0700.
添加第二个 resume
会导致 FiberError。
试试#2
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
1
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
2
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
sleep 1
puts "Done @ #{Time.now}."
这导致:
Waiting @ 2016-06-01 10:53:17 -0700.
Fiber1 starting @ 2016-06-01 10:53:17 -0700.
f1 back @ 2016-06-01 10:53:17 -0700 - .
Fiber2 starting @ 2016-06-01 10:53:17 -0700.
f2 back @ 2016-06-01 10:53:17 -0700 - .
Done @ 2016-06-01 10:53:18 -0700.
在这两种情况下,start/end时间相同,结果未返回。
Fiber 本身不会让你实现并行性,至少在不使用某种回调机制(例如 eventmachine 框架)的情况下不会。
你写的只是试图在代码块之间交错同步执行。你没有得到预期顺序的原因是因为当你模拟开球时,你从未在屈服后恢复纤维。
您可能会发现以下 post 有用,尤其是末尾的示例:
http://schmurfy.github.io/2011/09/25/on_fibers_and_threads.html
另一个显示纤程相互转移控制的示例:
https://gist.github.com/aprescott/971008
这应该会给你预期的结果:
#!/usr/bin/env ruby
require 'fiber'
f1 = Fiber.new do
puts "Fiber1 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber1 done @ #{Time.new}."
1
end
f2 = Fiber.new do
puts "Fiber2 starting @ #{Time.new}."
Fiber.yield
sleep 2
puts "Fiber2 done @ #{Time.new}."
2
end
puts "Waiting @ #{Time.new}."
r1 = f1.resume
puts "f1 back @ #{Time.new} - #{r1}."
r2 = f2.resume
puts "f2 back @ #{Time.new} - #{r2}."
# Resume right after the yield in the fiber block and
# execute until it encounters another yield or the block ends.
puts "Resuming f1"
f1.resume
puts "Resuming f2"
f2.resume
sleep 1
puts "Done @ #{Time.now}."
输出:
Waiting @ 2016-06-05 00:35:29 -0700.
Fiber1 starting @ 2016-06-05 00:35:29 -0700.
f1 back @ 2016-06-05 00:35:29 -0700 - .
Fiber2 starting @ 2016-06-05 00:35:29 -0700.
f2 back @ 2016-06-05 00:35:29 -0700 - .
Resuming f1
Fiber1 done @ 2016-06-05 00:35:31 -0700.
Resuming f2
Fiber2 done @ 2016-06-05 00:35:33 -0700.
Done @ 2016-06-05 00:35:34 -0700.