JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.43k stars 5.45k forks source link

print/println should block write final output #3787

Closed amitmurthy closed 9 years ago

amitmurthy commented 11 years ago

As folks start working with more parallel constructs, it will be good to have print/println do a block write of the final string.

julia> @sync begin
           for i in 1:3
               @async begin
                   println("Getting garbled")
               end
           end
       end
Getting garbledGetting garbledGetting garbled

The newline is written separately.

julia> @sync begin
           for i in 1:3
               @async begin
                   println(`Getting garbled`)
               end
           end
       end
```GGGeeettttttiiinnnggg   gggaaarrrbbbllleeeddd```
amitmurthy commented 11 years ago

"block" as in "write as a single block"

JeffBezanson commented 11 years ago

This behavior doesn't seem so great. It's easy to write a string and a newline in a single operation, but we don't want to have to worry about that sort of thing all the time. Maybe some sort of buffering is the answer? @loladiro Or use buffering for files and sockets, and make TTYs nonblocking?

Keno commented 11 years ago

libuv has the capability to write multiple things at once. It's just that our I/O system doesn't work that way. Making TTY's nonblocking seems fine, since writing to TTYs blocks the whole process anyway.

JeffBezanson commented 11 years ago

But, we have to arrange for the output to be consistent over the different kinds of streams. It would be bad to get different output when redirecting to a file than when testing by printing to the screen.

Keno commented 11 years ago

I don't think you can insist on that. In fact in most situations, you can probably not even depend on the output being the same between julia runs.

StefanKarpinski commented 11 years ago

Line buffering for text streams seems reasonable to me. But of course, we then need a distinction between printing to a text stream and printing to a byte stream, but we've talked about that before already.

JeffBezanson commented 11 years ago

Maybe we can''t insist on identical output in all sorts of scenarios, but getting the expected output at the prompt and then one of Amit's outputs above in a file seems gratuitous to me. The sensitivity to print("a\n") versus print('a','\n') is also a big pitfall. Even with nondeterminism, we can still pick a model of what sorts of phenomena are possible. Sure, if several tasks print messages I might get them in any order, but hopefully not interleaved character-by-character.

vtjnash commented 11 years ago

I suspect this is showing up now because we are now doing blocking writes, which presumably means there is a a task switch required by each call to the low-level write function.

Another possibility is to introduce locking:

print(s) = 
    lock(STDOUT) do
        print(STDOUT, text)
    end

function lock(fn, stream)
    lock(stream)
    try
        fn()
    finally
        unlock(stream)
    end
end

Where lock/unlock are the traditional recursive binary semaphores.

I'm not sure exactly where this would be put into the hierarchy of show/print.

JeffBezanson commented 11 years ago

No way; I don't want to have to use that lock stuff just to break some output into two print calls.

amitmurthy commented 9 years ago

Regression in https://github.com/JuliaLang/julia/commit/334a2be705fb0a742508cb05c22b37cd5956888c

Sisyphuss commented 9 years ago

Is the third post in #12600 a related issue?

amitmurthy commented 9 years ago

@Sisyphuss , #12600 is not related and not a bug. for introduces a new scope as documented. global x = i will result in the behavior you are looking for.

Sisyphuss commented 9 years ago

@amitmurthy no I meant the output format: the output "0" is between the print "x:1" and "x:2, x:3".

KristofferC commented 9 years ago

I also get a lot of interleaved printing between Julia and Jupyer in my notebooks.

amitmurthy commented 9 years ago

@KristofferC can you post examples? Currently only println to asynchronous streams is locked. If you are using print statements, you will need to manage it manually - http://docs.julialang.org/en/latest/manual/faq/#asynchronous-io-and-concurrent-synchronous-writes