|
|
|
|
|
by weberc2
2618 days ago
|
|
That's a big jump between OCaml and Go. I'm not familiar with ray tracing, but skimming the source code it mostly looks like it's doing floating point math; it doesn't look like it's using the runtime (no allocations, no virtual function calls, no scheduling, etc), so I'm surprised that Go is performing relatively poorly. I wonder if the performance gap is attributable to some overhead in Go's function calls? I know Go passes parameters on the stack instead of via registers... Maybe it's due to passing struct copies instead of references (looks like the C version passes references)? Generally poor code generation? Anyone else have ideas or care to profile? EDIT: From my 2015 MBP, Go (version 1.12) is indeed quite a lot slower than C, but only if you're doing an optimized build `-03`: tmp $ time ./gorb
real 1m15.128s
user 1m9.366s
sys 0m6.754s
tmp $ clang crb.c
tmp $ time ./a.out
real 1m13.041s
user 1m10.284s
sys 0m0.624s
tmp $ gcc crb.c -o crb -std=c11 -O3 -lm -D_XOPEN_SOURCE=600
tmp $ time ./crb
real 0m22.703s
user 0m22.550s
sys 0m0.073s
tmp $ clang crb.c -o crb -std=c11 -O3 -lm -D_XOPEN_SOURCE=600
tmp $ time ./crb
real 0m22.689s
user 0m22.564s
sys 0m0.060s
EDIT2: I re-modified the Go version (https://gist.github.com/weberc2/2aed4f8d3189d09067d564448367...) to pass references and that seems to put it on par with C (or I mistranslated, which is also likely): $ time ./gorb
real 0m19.282s
user 0m14.467s
sys 0m7.523s
|
|
(Where Go "wants" to play is that same benchmark, except including compilation time.)
A couple of the things below Go I suspect are bad implementations. I would expect a warmed-up C# to beat Go if both have reasonable (not super-crazy optimized implementations) or at least be at parity, and Luajit may also be a slow implementation. In both cases because ray-traced code is a great place for a JIT to come out and play. EDIT: Oh, I see C# is Mono, and not the Windows implementation. In that case that makes sense.
Oh, and I find it helpful to look at these things logarithmically. I think it matches real-world experiences somewhat better, even though we truly pay for performance in the linear world. From that perspective, it's still only the second largest. The largest is Haskell to Elixir, which is substantially larger. O'Caml->Go is large, but not crazily so; several other differences come close.