blob: 734f125bced6e3649b8be5a23b4486cf6b6f252c [file] [log] [blame] [view]
Dmitry Vyukov39df6ac2015-02-07 14:11:49 +03001# Compiler And Runtime Optimizations
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +01002
3This page lists optimizations done by the compilers. Note that these are not guaranteed by the language specification.
4
Josh Bleecher Snyder5afa4672015-02-04 09:50:03 -08005## Interface values
6
7### Zero-width types in interface values
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +01008
9Putting a zero-width type in an interface value doesn't allocate.
10
11* **gc:** 1.0+
12* **gccgo:** ?
13
Josh Bleecher Snyder5afa4672015-02-04 09:50:03 -080014### Word-sized value in an interface value
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +010015
16Putting a word-sized-or-less non-pointer type in an interface value doesn't allocate.
17
18* **gc:** 1.0-1.3, but *not* in 1.4+
19* **gccgo:** never
20
Josh Bleecher Snyder5afa4672015-02-04 09:50:03 -080021## string and []byte
22
23### Map lookup by []byte
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +010024
25For a map m of type map[string]T and []byte b, m[string(b)] doesn't allocate. (the temporary string copy of the byte slice isn't made)
26
27* **gc:** 1.4+
28* **gccgo:** ?
29
Brad Fitzpatrick25b2f972015-02-05 08:45:57 -080030### range over []byte(s)
31
32Avoiding allocating []byte of a string when ranging over the bytes:
33
34```
35 s := "foo"
36 for i, c := range []byte(s) {
37 // ...
38 }
39```
40
41* **gc:** 1.5+ (CL 3790)
42* **gccgo:** ?
43
Minux Maca122f42015-02-05 01:54:53 -050044## Escape analysis and Inlining
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +010045
Minux Maca122f42015-02-05 01:54:53 -050046Use `-gcflags -m` to observe the result of escape analysis and inlining
47decisions for the gc toolchain.
48
49(TODO: explain the output of `-gcflags -m`).
50
51### Escape analysis
52
Dmitry Vyukov9b727582015-02-05 12:21:41 +030053Gc compiler does global escape analysis across function and package boundaries. However, there are lots of cases where it gives up. For example, anything assigned to any kind of indirection (`*p = ...`) is considered escaped. Other things that can inhibit analysis are: function calls, package boundaries, slice literals, subslicing and indexing, etc. Full rules are too complex to describe, so check the `-m` output.
Dmitry Vyukov8e77f6b2015-02-05 12:20:57 +030054
Minux Maca122f42015-02-05 01:54:53 -050055* **gc:** 1.0+
56* **gccgo:** not yet.
57
58### Function Inlining
59
Dmitry Vyukov8e77f6b2015-02-05 12:20:57 +030060Only short and simple functions are inlined. To be inlined a function must contain less than ~40 expressions and does not contain complex things like function calls, loops, labels, closures, panic's, recover's, select's, switch'es, etc.
Dmitry Vyukov7da55092015-02-05 12:11:59 +030061
Minux Maca122f42015-02-05 01:54:53 -050062* **gc:** 1.0+
63* **gccgo:** -O1 and above.
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +010064
Josh Bleecher Snyder5afa4672015-02-04 09:50:03 -080065## Idioms
Brad Fitzpatrickf1d499c2015-02-02 12:21:07 +010066
Josh Bleecher Snyder5afa4672015-02-04 09:50:03 -080067### Optimized memclr
68
69For a slice or array s, loops of the form
70
71```go
72for i := range s {
73 a[i] = <zero value for element of s>
74}
75```
76
77are converted into efficient runtime memclr calls. [Issue](golang.org/issue/5373) and [commit](https://golang.org/change/f03c9202c43e0abb130669852082117ca50aa9b1).
78
79* **gc:** 1.5+
80* **gccgo:** ?
Dmitry Vyukov39df6ac2015-02-07 14:11:49 +030081
82## Non-scannable objects
83
Dmitry Vyukov9daa7da2015-02-07 14:12:35 +030084Garbage collector does not scan underlying buffers of slices, channels and maps when element type does not contain pointers (both key and value for maps). This allows to hold large data sets in memory without paying high price during garbage collection. For example, the following map won't visibly affect GC time:
Dmitry Vyukov39df6ac2015-02-07 14:11:49 +030085
86```go
87type Key [64]byte // SHA-512 hash
88type Value struct {
89 Name [32]byte
90 Balance uint64
91 Timestamp int64
92}
93m := make(map[Key]Value, 1e8)
94```
95
96* **gc:** 1.5+
97* **gccgo:** ?