Dmitry Vyukov | 39df6ac | 2015-02-07 14:11:49 +0300 | [diff] [blame] | 1 | # Compiler And Runtime Optimizations |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 2 | |
| 3 | This page lists optimizations done by the compilers. Note that these are not guaranteed by the language specification. |
| 4 | |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 5 | ## Interface values |
| 6 | |
| 7 | ### Zero-width types in interface values |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 8 | |
| 9 | Putting a zero-width type in an interface value doesn't allocate. |
| 10 | |
| 11 | * **gc:** 1.0+ |
| 12 | * **gccgo:** ? |
| 13 | |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 14 | ### Word-sized value in an interface value |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 15 | |
| 16 | Putting 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 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 21 | ## `string` and `[]byte` |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 22 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 23 | ### Map lookup by `[]byte` |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 24 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 25 | For 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) |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 26 | |
| 27 | * **gc:** 1.4+ |
| 28 | * **gccgo:** ? |
| 29 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 30 | ### `range` over `[]byte`(s) |
Brad Fitzpatrick | 25b2f97 | 2015-02-05 08:45:57 -0800 | [diff] [blame] | 31 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 32 | Avoiding allocating `[]byte` of a `string` when ranging over the bytes: |
Brad Fitzpatrick | 25b2f97 | 2015-02-05 08:45:57 -0800 | [diff] [blame] | 33 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 34 | ```go |
Brad Fitzpatrick | 25b2f97 | 2015-02-05 08:45:57 -0800 | [diff] [blame] | 35 | s := "foo" |
| 36 | for i, c := range []byte(s) { |
| 37 | // ... |
| 38 | } |
| 39 | ``` |
| 40 | |
| 41 | * **gc:** 1.5+ (CL 3790) |
| 42 | * **gccgo:** ? |
| 43 | |
Minux Ma | ca122f4 | 2015-02-05 01:54:53 -0500 | [diff] [blame] | 44 | ## Escape analysis and Inlining |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 45 | |
Minux Ma | ca122f4 | 2015-02-05 01:54:53 -0500 | [diff] [blame] | 46 | Use `-gcflags -m` to observe the result of escape analysis and inlining |
| 47 | decisions for the gc toolchain. |
| 48 | |
| 49 | (TODO: explain the output of `-gcflags -m`). |
| 50 | |
| 51 | ### Escape analysis |
| 52 | |
Dmitry Vyukov | 9b72758 | 2015-02-05 12:21:41 +0300 | [diff] [blame] | 53 | Gc 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 Vyukov | 8e77f6b | 2015-02-05 12:20:57 +0300 | [diff] [blame] | 54 | |
Minux Ma | ca122f4 | 2015-02-05 01:54:53 -0500 | [diff] [blame] | 55 | * **gc:** 1.0+ |
| 56 | * **gccgo:** not yet. |
| 57 | |
| 58 | ### Function Inlining |
| 59 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 60 | Only 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 Vyukov | 7da5509 | 2015-02-05 12:11:59 +0300 | [diff] [blame] | 61 | |
Minux Ma | ca122f4 | 2015-02-05 01:54:53 -0500 | [diff] [blame] | 62 | * **gc:** 1.0+ |
| 63 | * **gccgo:** -O1 and above. |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 64 | |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 65 | ## Idioms |
Brad Fitzpatrick | f1d499c | 2015-02-02 12:21:07 +0100 | [diff] [blame] | 66 | |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 67 | ### Optimized memclr |
| 68 | |
| 69 | For a slice or array s, loops of the form |
| 70 | |
| 71 | ```go |
| 72 | for i := range s { |
| 73 | a[i] = <zero value for element of s> |
| 74 | } |
| 75 | ``` |
| 76 | |
Oliver Beattie | a63d7cd | 2015-03-24 14:09:51 +0000 | [diff] [blame] | 77 | are converted into efficient runtime memclr calls. [Issue](https://github.com/golang/go/issues/5373) and [commit](https://golang.org/change/f03c9202c43e0abb130669852082117ca50aa9b1). |
Josh Bleecher Snyder | 5afa467 | 2015-02-04 09:50:03 -0800 | [diff] [blame] | 78 | |
| 79 | * **gc:** 1.5+ |
| 80 | * **gccgo:** ? |
Dmitry Vyukov | 39df6ac | 2015-02-07 14:11:49 +0300 | [diff] [blame] | 81 | |
| 82 | ## Non-scannable objects |
| 83 | |
Dmitry Vyukov | 9daa7da | 2015-02-07 14:12:35 +0300 | [diff] [blame] | 84 | Garbage 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 Vyukov | 39df6ac | 2015-02-07 14:11:49 +0300 | [diff] [blame] | 85 | |
| 86 | ```go |
| 87 | type Key [64]byte // SHA-512 hash |
| 88 | type Value struct { |
| 89 | Name [32]byte |
| 90 | Balance uint64 |
| 91 | Timestamp int64 |
| 92 | } |
| 93 | m := make(map[Key]Value, 1e8) |
| 94 | ``` |
| 95 | |
| 96 | * **gc:** 1.5+ |
| 97 | * **gccgo:** ? |