Okay, you’re right, I just saw this part:
POSIX requires that a read(2) that can be proved to occur after a
write() has returned will return the new data. Note that not all
filesystems are POSIX conforming.
I used to think the kernel read/write rules were slightly weaker than that. But now from the point of view of Julia code:
I didn’t mean that it won’t see them ever, it depends on the situation. But the rules don’t require changes to be visible, and so it is “not expected”, and one mustn’t write code that expects it. It still happens, depending on what exactly is going on. That is, if you specifically need the data to appear on the other side (e.g., in logs), you either flush it or you make sure that it’s unbuffered.
I just assume @info
and other such macros flush their outputs.
Your example highlights a particular behaviour of libc, that doesn’t quite mean that Julia will do the same thing.
So when I say it’s not buffered, this is what I mean. Try running the following program under strace:
strace julia -e 'foreach(println, 1:10)'
You will see that Julia prints everything one thing at a time:
...
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "7", 17) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "\n", 1
) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "8", 18) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "\n", 1
) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "9", 19) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "\n", 1
) = 1
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "10", 210) = 2
epoll_wait(3, [], 1024, 0) = 0
epoll_wait(3, [], 1024, 0) = 0
write(13, "\n", 1
) = 1
...
and the newlines are printed with one syscall each! This is one reason why when printing lots of data it can be so much faster to print it to iobuf=IOBuffer()
followed by write(stdout,take!(iobuf))
. It is also one reason why @show
can be slow with very large structures: every print
is a syscall. You can see there’s no buffering here.
You do not see the same thing with
strace julia -e 'foreach(println, 1:100)' >out
where you get
...
write(14, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 292) = 292
I don’t actually know what is buffering what precisely where in your original question. For example, it’s printing to file descriptor 13, even though stdout is normally fd 1, which means that something else is going on here. I assume it’s libuv that’s not buffering output to tty, but is buffering output to a file; it can definitely tell whether the script is being run with tty output vs a redirected >out
output to a file. Whatever it is, it’s not the same as libc.