I have some code that seems to work in practice, in testing, but not in benchmarks.
I am trying to understand why. When I put in print or do any type of debugging it appears I will get multiple test runs but code will get stuck before completing enough runs to generate a benchmark. I am not an experienced MT programmer but I am hoping this is a concept I have not learned yet.
Here is an extract of the code that is not working:
require "benchmark"
def locking_code(arr)
channel = Channel(Int64).new
spawn do
acc = 0_i64
index = 0
while index < arr.size
acc += arr[index]
index += 2
end
channel.send(acc)
end
spawn do
acc = 0_i64
index = 1
while index < arr.size
acc += arr[index]
index += 2
end
channel.send(acc)
end
channel.receive + channel.receive
end
arr = (1_i64..100_000_i64).to_a
Benchmark.ips do |ips|
ips.report("locking") { locking_code(arr) }
end
I am running this on an M2 MacBook pro
Darwin jbook.local 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 20:59:58 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6020 arm64 arm Darwin
building the binary with
crystal build -Dpreview_mt --release benchmarks/locking_code.cr -o bin/locking
running with
CRYSTAL_WORKERS=8 bin/locking
Also weirdly using Fiber.yield
works for me. it has poor performance so I was trying channels. Which is how I got down this path. If anyone can explain Fiber.yield
vs channel performance I would be really interested.