while true do
io.write "1"
end
PUC-Rio 5.1: 25 MiB/sPUC-Rio 5.4: 25 MiB/s
LuaJIT 2.1.0-beta3: 550 MiB/s <--- WOW
They all go slightly faster if you localize the reference to `io.write`
local write = io.write
while true do
write "1"
endNo noticeable difference for LuaJIT, which makes sense, since JIT should figure it out without help.
5.1 and 5.4 show about ~8% improvement.
main = putStr (repeat '1')
[Edit: as pointed out below, this is no longer the case!]Strings are printed one character at a time in Haskell. This choice is justified by unpredictability of the interaction between laziness and buffering; I am uncertain it's the correct choice, but the proper response is to use Text where performance is relevant.
poll([{fd=1, events=POLLOUT}], 1, 0) = 1 ([{fd=1, revents=POLLOUT}])
write(1, "11111111111111111111111111111111"..., 8192) = 8192
poll([{fd=1, events=POLLOUT}], 1, 0) = 1 ([{fd=1, revents=POLLOUT}])
write(1, "11111111111111111111111111111111"..., 8192) = 8192
With the recursive code, it buffered the output in the same way but bugged the kernel a whole lot more in-between writes. Not exactly sure what is going on: poll([{fd=1, events=POLLOUT}], 1, 0) = 1 ([{fd=1, revents=POLLOUT}])
write(1, "11111111111111111111111111111111"..., 8192) = 8192
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=0, tv_nsec=920390843}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=0, tv_nsec=920666397}) = 0
...
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
poll([{fd=1, events=POLLOUT}], 1, 0) = 1 ([{fd=1, revents=POLLOUT}])
write(1, "11111111111111111111111111111111"..., 8192) = 8192I'm also not sure what's going on in the second case. IIRC, at some point historically, a sufficiently tight loop could cause trouble with handling SIGINT, so it might be related to some overagressive workaround for that?
Python3: 3 MiB/s
Node: 350 KiB/s
Lua: 12 MiB/s
Haskell: 5 MiB/s Awk: 4.2 MiB/s