Will fmt.Sprintf going to be faster in future?

1,832 views
Skip to first unread message

davy zhang

unread,
Mar 5, 2013, 12:05:47 PM3/5/13
to golan...@googlegroups.com
fmt.Sprintf is slow when cast int to string like "%d"

I tracked down using pprof, it shows 
ROUTINE ====================== fmt.(*operator++).fmtPointer in /usr/local/go/src/pkg/runtime/print.c
   109    934 Total samples (flat / cumulative)
     .      .  365: void
     .      .  366: runtime·typestring(Eface e, String s)
     .      .  367: {
     .      .  368: s = *e.type->string;
   109    934  369: FLUSH(&s);
---
     .      .  370: }

which kills the performance

Is there any chance to make it faster?

or there's any faster way to cast int to string?

strconv is even slower ....


go test -test.bench "FormatInt"

PASS

BenchmarkFormatInt       200000           7852 ns/op

ok       strconv     2.636s





minux

unread,
Mar 5, 2013, 1:39:24 PM3/5/13
to davy zhang, golan...@googlegroups.com
On Wed, Mar 6, 2013 at 1:05 AM, davy zhang <davy...@gmail.com> wrote:
> fmt.Sprintf is slow when cast int to string like "%d"
> Is there any chance to make it faster?
>
> or there's any faster way to cast int to string?
>
> strconv is even slower ....
Did you read the source of this benchmark? how did you come to this conclusion?
Note: the result doesn't mean strconv.FormatInt needs 7852ns to format
one integer.
strconv.FormatInt should be much faster than fmt.Sprintf("%d", i).
> go test -test.bench "FormatInt"
> BenchmarkFormatInt 200000 7852 ns/op

If you really care about performance, you shouldn't use string at all, you'd
better use []byte and strconv.AppendInt to avoid generating garbage for strings.

bryanturley

unread,
Mar 5, 2013, 2:41:56 PM3/5/13
to golan...@googlegroups.com, davy zhang

Is the speed of Sprintf / strconv.* a real issue?
Are you doing a good bit of string generation?

Dave Cheney

unread,
Mar 5, 2013, 3:39:42 PM3/5/13
to davy zhang, golan...@googlegroups.com
Please supply the code for your benchmark, I will try to reproduce this issue.
> --
> 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/groups/opt_out.
>
>

Kevin Gillette

unread,
Mar 5, 2013, 4:00:30 PM3/5/13
to golan...@googlegroups.com, davy zhang
My tests (code at http://play.golang.org/p/YF76ATMk_q) show Sprint and Sprintf to have roughly equivalent speeds, with FormatInt being ~3.5x faster than fmt offerings, and AppendInt ~2x faster than FormatInt. All of these figures should be considered only in the context of running these functions in a tight loop; used in most other contexts, the difference between the slowest and fastest would be entirely negligible.

minux

unread,
Mar 5, 2013, 4:03:04 PM3/5/13
to Kevin Gillette, golan...@googlegroups.com, davy zhang

On Wednesday, March 6, 2013, Kevin Gillette wrote:
My tests (code at http://play.golang.org/p/YF76ATMk_q) show Sprint and Sprintf to have roughly equivalent speeds, with FormatInt being ~3.5x faster than fmt offerings, and AppendInt ~2x faster than FormatInt. All of these figures should be considered only in the context of running these functions in a tight loop; used in most other contexts, the difference between the slowest and fastest would be entirely negligible.
confirmed.
this result roughly matches my own benchmarks on amd64.

davy zhang

unread,
Mar 5, 2013, 9:31:48 PM3/5/13
to golan...@googlegroups.com, davy zhang
here is the test code

here is the cfmt wrapper which didn't offer much speed

I got the result:
BenchmarkCFmtYear 1000000      1125 ns/op
BenchmarkFmt 1000000      1614 ns/op
BenchmarkRenderTime  500000      3881 ns/op
BenchmarkRenderTimeManual 1000000      2664 ns/op

as the fmt's part add the time used will significantly rise

I am doing a log job in my project so the time format is inevitable, and I don't want it be a bottle-neck

Dave Cheney

unread,
Mar 5, 2013, 9:45:30 PM3/5/13
to davy zhang, golan...@googlegroups.com
Hmm, Fmt.Sprintf appears to be the fastest in your example, but only
the second fastest on my machine.

I am deliberately ignoring your C wrapper, because, IMO, if you wanted
to write C, you should use C, not Go.

results from running linux/amd64 somewhere near tip.

lucky(~/src/tyme) % go test -bench=.
testing: warning: no tests to run
PASS
BenchmarkFmt 2000000 823 ns/op
BenchmarkRenderTime 5000000 572 ns/op
BenchmarkRenderTimeManual 1000000 1594 ns/op

davy zhang

unread,
Mar 5, 2013, 9:58:48 PM3/5/13
to Dave Cheney, golan...@googlegroups.com
Very interesting, I am using the release version of go 1.0.3 with mackbookpro i7 2.66Ghz

the result is of BenchmarkRenderTime is way tooooo different :D

I check it on my linux server amazon aws

BenchmarkFmt     1000000              1950 ns/op
BenchmarkRenderTime       500000              4929 ns/op
BenchmarkRenderTimeManual         500000              3379 ns/op
BenchmarkFormatInt      10000000               232 ns/op
BenchmarkAppendInt      20000000               110 ns/op
BenchmarkSprint  1000000              6347 ns/op
BenchmarkSprintf          200000              6493 ns/op

code here :

which version of go do you use?

Bryan Turley

unread,
Mar 5, 2013, 10:05:21 PM3/5/13
to davy zhang, golan...@googlegroups.com, Dave Cheney


On Mar 5, 2013 8:59 PM, "davy zhang" <davy...@gmail.com> wrote:
>
> Very interesting, I am using the release version of go 1.0.3 with mackbookpro i7 2.66Ghz
>
> the result is of BenchmarkRenderTime is way tooooo different :D
>
> I check it on my linux server amazon aws
>
> BenchmarkFmt     1000000              1950 ns/op
> BenchmarkRenderTime       500000              4929 ns/op
> BenchmarkRenderTimeManual         500000              3379 ns/op
> BenchmarkFormatInt      10000000               232 ns/op
> BenchmarkAppendInt      20000000               110 ns/op
> BenchmarkSprint  1000000              6347 ns/op
> BenchmarkSprintf          200000              6493 ns/op
>
> code here :
> http://play.golang.org/p/37ZJIZUKfn
>
> which version of go do you use?
>
>

I bet he uses tip and you shouldn't benchmark on virtual servers like amazon aws.  Benchmark on a dedicated machine with next to nothing running for the best results.

> You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/pN1AtedMX3g/unsubscribe?hl=en-US.
> To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Dave Cheney

unread,
Mar 5, 2013, 10:14:06 PM3/5/13
to davy zhang, golan...@googlegroups.com
From the previous message

"results from running linux/amd64 somewhere near tip."

davy zhang

unread,
Mar 5, 2013, 10:16:08 PM3/5/13
to golan...@googlegroups.com, davy zhang
Thanks for the benchmark code and sorry for the wrong conclusion, I didn't take a clearer look at built-in benchmark code

I'll try strconv Format and AppendInt

it apear that AppendInt achieved the fastest speed

BenchmarkFmt 1000000      1631 ns/op
BenchmarkRenderTime  500000      3903 ns/op
BenchmarkRenderTimeManual 1000000      2756 ns/op
BenchmarkRenderTimeConv 1000000      1489 ns/op
BenchmarkRenderTimeAppend 2000000       792 ns/op
BenchmarkFormatInt 10000000       175 ns/op
BenchmarkAppendInt 20000000        82.6 ns/op
BenchmarkSprint 5000000       559 ns/op
BenchmarkSprintf 5000000       552 ns/op

code here

Thanks for the help
Reply all
Reply to author
Forward
0 new messages