cmd/compile: for-loops cannot be inlined #14768

Open
dsnet opened this Issue Mar 11, 2016 · 3 comments

Comments

Projects
None yet
4 participants
Member

dsnet commented Mar 11, 2016

Using go devel +ed4a27a

Currently, functions with for-loops are not inline-able, would be nice if they did. Not long ago, I used a non-idiomatic goto in order to cheat around the inliner.

@dr2chase

@bradfitz bradfitz added this to the Unplanned milestone Mar 11, 2016

@dr2chase dr2chase self-assigned this Mar 13, 2016

Member

ALTree commented Mar 28, 2016

For reference, the easy part (inlining for loops with no range and no continue/break)
inlines 924 additional calls in go install std and gives mixed results on the go1 benchmarks

name                     old time/op    new time/op    delta
BinaryTree17-4              3.00s ± 3%     2.96s ± 4%     ~             (p=0.548 n=5+5)
Fannkuch11-4                2.29s ± 0%     2.29s ± 0%     ~             (p=0.056 n=5+5)
FmtFprintfEmpty-4          50.4ns ± 0%    50.7ns ± 2%     ~             (p=0.556 n=4+5)
FmtFprintfString-4          134ns ± 0%     134ns ± 0%     ~     (all samples are equal)
FmtFprintfInt-4             133ns ± 0%     133ns ± 0%     ~     (all samples are equal)
FmtFprintfIntInt-4          201ns ± 0%     198ns ± 0%     ~             (p=0.079 n=4+5)
FmtFprintfPrefixedInt-4     201ns ± 0%     197ns ± 0%   -1.79%          (p=0.000 n=5+4)
FmtFprintfFloat-4           291ns ± 2%     284ns ± 1%   -2.20%          (p=0.040 n=5+5)
FmtManyArgs-4               845ns ± 0%     841ns ± 1%     ~             (p=0.056 n=5+5)
GobDecode-4                7.81ms ± 1%    7.90ms ± 1%   +1.22%          (p=0.008 n=5+5)
GobEncode-4                6.55ms ± 1%    6.27ms ± 0%   -4.24%          (p=0.008 n=5+5)
Gzip-4                      268ms ± 0%     269ms ± 1%     ~             (p=0.690 n=5+5)
Gunzip-4                   36.8ms ± 0%    36.6ms ± 0%   -0.60%          (p=0.008 n=5+5)
HTTPClientServer-4         58.5µs ± 1%    61.8µs ± 0%   +5.65%          (p=0.008 n=5+5)
JSONEncode-4               17.2ms ± 1%    16.9ms ± 2%   -1.77%          (p=0.016 n=5+5)
JSONDecode-4               51.5ms ± 0%    52.1ms ± 1%   +1.16%          (p=0.008 n=5+5)
Mandelbrot200-4            4.77ms ± 0%    4.74ms ± 1%     ~             (p=0.151 n=5+5)
GoParse-4                  3.58ms ± 0%    3.54ms ± 1%   -1.10%          (p=0.016 n=5+5)
RegexpMatchEasy0_32-4      81.5ns ± 0%    82.1ns ± 0%   +0.74%          (p=0.016 n=4+5)
RegexpMatchEasy0_1K-4       199ns ± 2%     196ns ± 0%   -1.51%          (p=0.048 n=5+5)
RegexpMatchEasy1_32-4      81.2ns ± 1%    82.9ns ± 0%   +2.04%          (p=0.016 n=5+4)
RegexpMatchEasy1_1K-4       360ns ± 2%     356ns ± 1%     ~             (p=0.167 n=5+5)
RegexpMatchMedium_32-4      125ns ± 1%     124ns ± 0%     ~             (p=0.167 n=5+5)
RegexpMatchMedium_1K-4     38.8µs ± 1%    37.9µs ± 1%   -2.54%          (p=0.008 n=5+5)
RegexpMatchHard_32-4       1.98µs ± 0%    1.95µs ± 0%   -1.73%          (p=0.000 n=5+4)
RegexpMatchHard_1K-4       59.7µs ± 0%    58.6µs ± 0%   -1.85%          (p=0.016 n=4+5)
Revcomp-4                   437ms ± 0%     448ms ± 1%   +2.65%          (p=0.008 n=5+5)
Template-4                 62.8ms ± 0%    62.8ms ± 0%     ~             (p=0.841 n=5+5)
TimeParse-4                 328ns ± 0%     295ns ± 0%  -10.17%          (p=0.000 n=5+4)
TimeFormat-4                357ns ± 1%     349ns ± 3%     ~             (p=0.111 n=5+5)
Member

dsnet commented Mar 28, 2016

Thanks for doing this; it was not exactly the results I was hoping for ;)

Are you aware of which loops in HTTPClientServer were inlined? I'm curious about the 5% increase in time.

Member

ALTree commented Mar 28, 2016

grepping for "http" in the diff between the outputs for go install -gcflags -m std says

> ../go/src/net/http/cgi/host.go:191: inlining call to filepath.Split
> ../go/src/net/http/cgi/host.go:191: inlining call to filepath.VolumeName
> ../go/src/net/http/cgi/host.go:191: inlining call to filepath.volumeNameLen
> ../go/src/net/http/cgi/host.go:191: inlining call to os.IsPathSeparator
> ../go/src/net/http/cookie.go:215: inlining call to parseCookieValue
> ../go/src/net/http/cookie.go:215: inlining call to validCookieValueByte
> ../go/src/net/http/cookie.go:58: inlining call to parseCookieValue
> ../go/src/net/http/cookie.go:58: inlining call to validCookieValueByte
> ../go/src/net/http/cookie.go:78: inlining call to parseCookieValue
> ../go/src/net/http/cookie.go:78: inlining call to validCookieValueByte
> ../go/src/net/http/cookiejar/punycode.go:136: inlining call to ascii
> ../go/src/net/http/cookiejar/punycode.go:141: inlining call to ascii
> ../go/src/net/http/cookiejar/punycode.go:89: inlining call to adapt
> ../go/src/net/http/fs.go:163: inlining call to filepath.Ext
> ../go/src/net/http/fs.go:163: inlining call to os.IsPathSeparator
> ../go/src/net/http/fs.go:483: inlining call to filepath.Split
> ../go/src/net/http/fs.go:483: inlining call to filepath.VolumeName
> ../go/src/net/http/fs.go:483: inlining call to filepath.volumeNameLen
> ../go/src/net/http/fs.go:483: inlining call to os.IsPathSeparator
> ../go/src/net/http/h2_bundle.go:2962: inlining call to http2validHeaderFieldValue
> ../go/src/net/http/h2_bundle.go:3015: inlining call to http2validHeaderFieldValue
> ../go/src/net/http/h2_bundle.go:4541: inlining call to textproto.isASCIISpace
> ../go/src/net/http/h2_bundle.go:4541: inlining call to textproto.TrimString
> ../go/src/net/http/h2_bundle.go:4550: inlining call to textproto.isASCIISpace
> ../go/src/net/http/h2_bundle.go:4550: inlining call to textproto.TrimString
> ../go/src/net/http/h2_bundle.go:6014: inlining call to http2validHeaderFieldValue
> ../go/src/net/http/h2_bundle.go:6401: inlining call to http2validHeaderFieldValue
> ../go/src/net/http/header.go:154: inlining call to textproto.isASCIISpace
> ../go/src/net/http/header.go:154: inlining call to textproto.TrimString
> ../go/src/net/http/internal/chunked.go:124: inlining call to isASCIISpace
> ../go/src/net/http/internal/chunked.go:124: inlining call to trimTrailingWhitespace
> ../go/src/net/http/lex.go:139: inlining call to isOWS
> ../go/src/net/http/lex.go:139: inlining call to trimOWS
> ../go/src/net/http/lex.go:141: inlining call to isOWS
> ../go/src/net/http/lex.go:141: inlining call to trimOWS
> ../go/src/net/http/server.go:1105: inlining call to textproto.isASCIISpace
> ../go/src/net/http/server.go:1105: inlining call to textproto.TrimString
> ../go/src/net/http/server.go:1114: inlining call to textproto.isASCIISpace
> ../go/src/net/http/server.go:1114: inlining call to textproto.TrimString
> ../go/src/net/http/server.go:723: inlining call to validHostHeader
> ../go/src/net/http/server.go:731: inlining call to isCTL
> ../go/src/net/http/server.go:731: inlining call to isLWS
> ../go/src/net/http/server.go:731: inlining call to validHeaderValue
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:101: inlining call to constantTimeStringCompare
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:127: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:127: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:127: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:141: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:141: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:141: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:154: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:187: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:196: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:225: inlining call to HuffmanEncodeLength
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:228: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:232: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:42: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:42: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:42: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:55: inlining call to appendTableSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:55: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:58: inlining call to appendTableSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:58: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:63: inlining call to appendIndexed
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:63: inlining call to appendVarInt
> ../go/src/vendor/golang.org/x/net/http2/hpack/encode.go:92: inlining call to constantTimeStringCompare
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:137: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:137: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:137: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:160: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:160: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:175: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:175: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:217: inlining call to constantTimeStringCompare
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:226: inlining call to constantTimeStringCompare
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:443: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:443: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:443: inlining call to (*HeaderField).size
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:97: inlining call to (*dynamicTable).evict
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:97: inlining call to (*dynamicTable).setMaxSize
> ../go/src/vendor/golang.org/x/net/http2/hpack/hpack.go:97: inlining call to (*HeaderField).size

No idea which one of these is the culprit for the slowdown.

@mvdan mvdan changed the title from cmd/compile: for-loops cant be inlined to cmd/compile: for-loops cannot be inlined Aug 17, 2017

wallyqs added a commit to wallyqs/gnatsd that referenced this issue Sep 8, 2017

Remove for loop in parseSize to enable inlining
Using a goto based loop makes it become a leaf function which can be
inlined, making us get a slight performance increase in the fast path.
See: golang/go#14768

wallyqs added a commit to wallyqs/gnatsd that referenced this issue Sep 8, 2017

Remove for loop in parseSize to enable inlining
Using a goto based loop makes it become a leaf function which can be
inlined, making us get a slight performance increase in the fast path.
See: golang/go#14768
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment