Does fmt.Fprint use WriteString ?

708 views
Skip to first unread message

codi...@gmail.com

unread,
Apr 21, 2019, 9:13:22 PM4/21/19
to golang-nuts
Hi gophers! Just wondering if in a Handler I should (w is the http.ResponseWriter):

fmt.Fprint(w, "Hello world")

or is it better to 

io.WriteString(w, "Hello world")

or is it the same if fmt.Fprint already uses WriteString internally?

Constantin Konstantinidis

unread,
Apr 22, 2019, 9:28:50 AM4/22/19
to golang-nuts
fmt.Fprint is calling io.WriteString as you can this comment and the code around indicates.

codi...@gmail.com

unread,
Apr 22, 2019, 1:46:00 PM4/22/19
to golang-nuts
Actually, that comment points to the implementation of WriteString for the fmt package's internal pp type, which in turn is used by other fmt functions to handle strings efficiently. After scanning that source file some more, and the source file for io.WriteString (https://golang.org/src/io/io.go?s=10163:10218#L279) I can see that even though fmt.Fprint and others don't use io.WriteString directly, they do exactly the same thing io.WriteString does, which is calling the destination's Write method exactly once and only once, thus avoiding extra allocations. So in conclusion, from what I see, it's equally efficient to write a string to a writer via io.WriteString or fmt.Fprint.

Constantin Konstantinidis

unread,
Apr 23, 2019, 1:43:55 PM4/23/19
to golang-nuts
The result is equivalent but a micro-benchmark shows that pkg io is 3x faster.

go version go1.12.2 windows/amd64
pkg: github.com/iWdGo/GoCompilerEfficiency/src/writestring
BenchmarkFmtWriteString-4         500000              2002 ns/op
BenchmarkIoWriteString-4         2000000               635 ns/op
PASS

This is irrelevant is the string requires some build.
(sorry for the typo above)

codi...@gmail.com

unread,
Apr 24, 2019, 9:48:27 AM4/24/19
to golang-nuts
That's interesting and good to know. I guess it should be expected given that Fprint does a bit more work using it's internal printer struct and buffer.

Louki Sumirniy

unread,
May 3, 2019, 10:38:31 AM5/3/19
to golang-nuts
There is a big difference between the parameters of these two functions. One is a slice of interface, the other is only a a single string parameter. fmt print functions all have nasty messy interface switching and reflection internally hence the significant overhead.

A lot of people clearly don't know this, also - there is a builtin print() and println() function in Go. If the output is stdout, these are probably the most efficient ways to thow strings at it. Clearly the same goes for io.WriteString, but with the option of using another Writer instead of stdout.

Robert Engels

unread,
May 3, 2019, 10:54:37 AM5/3/19
to Louki Sumirniy, golang-nuts
I suggest that it might benefit you to understand cost of IO. In most systems the IO cost dwarfs the CPU cost of optimizations like these. I am not saying it never matters - I have significant HFT experience and sone HPC - but in MOST cases it holds true. 

So micro optimizing the CPU usually has little effect on total runtime. 

Broken algs, ON^2, are another story. 
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Louki Sumirniy

unread,
May 3, 2019, 11:01:53 AM5/3/19
to golang-nuts
You are totally correct about this - the only real performance booster for IO bound operations is buffering, which delays the writes to be less frequent or follow a clock.

I wrote a logging library that used channels, and it was pointed out to me that this doesn't have a big effect. But I think it *should* allow a multi-core system to keep one or a few cores dedicated to the CPU bound processing part of the work, and the IO, with all its waiting, to other threads/cores. 

So, using WriteString would make sense, if the Writer it addresses is buffered, if performance is needing to be squeezed just a little more. But the buffer matters far more.


On Friday, 3 May 2019 16:54:37 UTC+2, Robert Engels wrote:
I suggest that it might benefit you to understand cost of IO. In most systems the IO cost dwarfs the CPU cost of optimizations like these. I am not saying it never matters - I have significant HFT experience and sone HPC - but in MOST cases it holds true. 

So micro optimizing the CPU usually has little effect on total runtime. 

Broken algs, ON^2, are another story. 

On May 3, 2019, at 9:38 AM, Louki Sumirniy <louki.sumi...@gmail.com> wrote:

There is a big difference between the parameters of these two functions. One is a slice of interface, the other is only a a single string parameter. fmt print functions all have nasty messy interface switching and reflection internally hence the significant overhead.

A lot of people clearly don't know this, also - there is a builtin print() and println() function in Go. If the output is stdout, these are probably the most efficient ways to thow strings at it. Clearly the same goes for io.WriteString, but with the option of using another Writer instead of stdout.

On Monday, 22 April 2019 03:13:22 UTC+2, codi...@gmail.com wrote:
Hi gophers! Just wondering if in a Handler I should (w is the http.ResponseWriter):

fmt.Fprint(w, "Hello world")

or is it better to 

io.WriteString(w, "Hello world")

or is it the same if fmt.Fprint already uses WriteString internally?

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Robert Engels

unread,
May 3, 2019, 12:18:33 PM5/3/19
to Louki Sumirniy, golang-nuts
Parallelization is another story. If the cores are available and the workload fits, you can get linear speed ups - especially when the IO is parallelized across devices - which is nearly impossible via micro cpu optimizations. 
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Marvin Renich

unread,
May 8, 2019, 1:55:04 PM5/8/19
to golang-nuts
[Sorry for the late reply; I was having technical difficulties!]

* Louki Sumirniy <louki.sumir...@gmail.com> [190503 10:39]:
> A lot of people clearly don't know this, also - there is a builtin print()
> and println() function in Go. If the output is stdout, these are probably
> the most efficient ways to thow strings at it.

FYI, these are documented at https://golang.org/ref/spec#Bootstrapping

Current implementations provide several built-in functions useful
during bootstrapping. These functions are documented for completeness
but are not guaranteed to stay in the language. They do not return a
result.

So, if you use print and println, be aware that they are not really
intended for production use and are not covered by the language
compatibility guarantee.

...Marvin

Reply all
Reply to author
Forward
0 new messages