Reputation: 356
I'm trying to research some details about efficiency with Go because I'm new to it. One of the tests I wanted to perform was to see if Go's fmt.Print
was faster or slower than os.Stdout.WriteLine
Here are the results.
fmt.Print speed
[kamori@kamori-pc playground]$ cat print.go
package main
import "fmt"
import "os"
func main(){
os.Stderr.WriteString("Printing Hello World! 1000000000 times")
for i := 0; i < 1000000000; i++{
fmt.Print("Hello World!\n")
}
}
[kamori@kamori-pc playground]$ go build print.go
[kamori@kamori-pc playground]$ time ./print >/dev/null
Printing Hello World! 1000000000 times
real 13m9.127s
user 8m52.461s
sys 4m15.433s
os.Stdout.WriteString
[kamori@kamori-pc playground]$ cat stdoutwrite.go
package main
import "os"
func main(){
os.Stderr.WriteString("StdoutWriting Hello World! 1000000000 times")
for i := 0; i < 1000000000; i++{
os.Stdout.WriteString("Hello World!\n")
}
}
[kamori@kamori-pc playground]$ go build stdoutwrite.go
[kamori@kamori-pc playground]$ time ./stdoutwrite >/dev/null
StdoutWriting Hello World! 1000000000 times
real 11m36.198s
user 7m31.211s
sys 4m0.080s
I understand this isn't the best way to test this process. But it was the one I chose and it was interesting. I'm still curious to know the differences but the results kinda make sense to me. However, just for fun, I did the same thing with Python 3 and it went way faster
Python 3
[kamori@kamori-pc playground]$ cat print.py
for i in range(1000000000):
print("Hello World!")
[kamori@kamori-pc playground]$ time python3 print.py >/dev/null
real 6m46.542s
user 6m44.450s
sys 0m0.836s
Here is version details
[kamori@kamori-pc playground]$ go version
go version go1.13.4 linux/amd64
[kamori@kamori-pc playground]$ python --version
Python 3.7.4
[kamori@kamori-pc playground]$ uname -a
Linux kamori-pc 4.19.59-rt23-MANJARO #1 SMP PREEMPT RT Sat Jul 20 07:14:03 UTC 2019 x86_64 GNU/Linux
My question is, why did python out perform Go? My expectation was Go would be faster as its a compiled language. Sure there isn't a ton of logic that needs to be figured out on the fly so Python might be able to take some shortcuts. But, these workloads seem really small, IMO both languages should be returning pretty fast besides the startup overhead.
--- Edit ---
I saw comments about using bufio to buffer my writes. And holy moly.
[kamori@kamori-pc playground]$ cat bufferio.go
package main
//import "fmt"
import "os"
import "bufio"
func main(){
os.Stderr.WriteString("Printing Hello World! 1000000000 times")
mywrite := bufio.NewWriter(os.Stdout)
for i := 0; i < 1000000000; i++{
mywrite.WriteString("Hello World!\n")
}
}
[kamori@kamori-pc playground]$ go build bufferio.go
[kamori@kamori-pc playground]$ time ./bufferio >/dev/null
Printing Hello World! 1000000000 times
real 0m9.882s
user 0m9.003s
sys 0m0.865s
--- Edit2 --- For dave's answer I went ahead and set flush=True and here are the results. This is what I expected to see in my original comparison. Looks like buffering saves the day!
[kamori@kamori-pc playground]$ cat print_with_flush_true.py
for i in range(1000000000):
print("Hello World!", flush=True)
[kamori@kamori-pc playground]$ time python3 print_with_flush_true.py >/dev/null
real 27m38.319s
user 23m15.274s
sys 4m16.869s
Upvotes: 2
Views: 426
Reputation: 64727
Python3 buffers the output of print
.
https://docs.python.org/3/library/functions.html#print
Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.
You would need to do:
print("Hello World!", flush=True)
for the tests to be equivalent
Upvotes: 6