A few notable changes in Go 1.7

Source: Internet
Author: User
Tags benchmark
This is a creation in Article, where the information may have evolved or changed.

0. Starting from release cycle

Beginning with the Go 1.3 release, the development cycle of the Golang core development team gradually stabilized. After the go 1.4, Go1.5 and go 1.6 practices, the great God Russ Cox roughly defines the general flow of Go Release cycle on the Go wiki:

    1. Six months a major release version.
    2. Release process start time: Every August 1 and next February 1 (the actual release date may be this day, may also be postponed for a few days).
    3. During the six-month cycle, the first three months are the active Development,then feature freezes (about November 1 and the next May 1). The next three months are test and polish.
    4. Start-up schedule for the next release: July 15 and January 15, the version plan lasts 15 days, including a discussion of the main features to be implemented in this major release, and a bug that was left over from the previous fix.
    5. Several stages prior to release: several of the beta versions (typically 2-3), Release Candidate versions (typically 1-2), and the final release version.
    6. The maintenance of the release version of Major is demonstrated through a series of minor versions, mainly to fix some serious problems or security issues that lead to crash, such as major release version go 1.6 now has go 1.6.1 and go 1.6.22 subsequent minor releases.

When developing the next version of the launch plan, it is common for Russ Cox to initiate discussions at Golang-dev Group, and other core developer discuss what they are going to do in the next version of the discussion post. Give all developers a general overview of the features and bug fixes that may be included in the next release. But whether these things can eventually be included in the next release version, but also depends on the development stage feature code can be completed, through the review and added to the main trunk, if too late to join, this function may be placed in the next major Release, for example, SSA missed go 1.6 (because the go 1.5 changes are large, leaving the time for Go 1.6 shorter) and placed in go 1.7.

Personally, the go community uses a "democratic centralism" culture, in which a minority of Google's Golang core team has a real say, especially a few of the first big gods to join the go team, such as Rob Pike old man, Russ Cox, and Ian Lance Taylor and so on. Of course, most of the reasonable advice is still a merge into the go code, but some and go philosophy has deviated from the idea, such as adding generics, adding new types, improve error handling, basically are Rob Pike old man sternly refused, at least go 1 compatible version, everyone is definitely invisible. As for Go 2, even the go core team can't afford to pack a ticket saying that there will be a new language specification. But some of the comments from Rob Pike's previous stages can roughly figure out Pike's old man is rethinking the design of Go 1, and maybe he's working on the language specification for Go 2 ^_^. This "culture" is not to be appreciated by many open source developers, at the Gopherchina 2016 Congress, we have had a deep debate on this "some dictatorship" culture, especially in contrast to Rust's "absolute democracy" culture. A matter of opinion, this is not in-depth. Personally feel that go core team's current practice is still good to keep the go language version of the ideal compatibility and development of consistency, for a project-oriented language, this may be a more important thing for developers; programming language syntax "jumping" between different versions Evolution may bring freshness in a short period of time, but in the long run, there will be a heavy burden on code reading and maintenance.

Let's go back to the chase. What are some notable changes that Go 1.7 brings? We'll announce ^_^. (The go version used by the following tests is Go 1.7 beta2).

One, language

The goal of Go 1.7 in the release planning phase is to improve and optimize (polishing), so the Go Language (specification) specification continues to be compatible with go 1, so theoretically the release of Go 1.7 is transparent to previous GO 1 compliant programs, Existing code can be compiled and executed correctly through go 1.7.

However, go 1.7 also made a extremely-tiny change to Go1 specs's description of "terminating statements":

A statement list ends in a terminating statement if the list is not empty and its final statement is terminating.=>A statement list ends in a terminating statement if the list is not empty and its final non-empty statement is terminating.

Specs is abstract, examples are vivid, we use an example to illustrate this change:

// go17-examples/language/f.gopackage ffunc f() int {    return 3    ;}

For the list of statements in the body of the F function in F.go (statement list), all versions of Go compiler or GCCGO compiler will be considered as "return 3″ this terminating Statement terminate, even after the return statement there is a ";" It doesn't matter. But the Gotype tool before go 1.7 is checked strictly according to the instructions in go 1 specs before go 1.7, because the final statement is ";" – an empty Statement,gotype will prompt: "Missing return":

// Go 1.7前版本的gotype$gotype f.gof.go:6:1: missing return

So there is Gotype and GC, GCCGO behavior inconsistent! For this go 1.7 did some specs changes, the statements list terminate point from "final statement" to "final Non-empty statement", so that even after the ";" Also matter. Then the same command was executed with the Gotype in Go 1.7, but the results were different:

// Go 1.7的gotype$gotype f.go没有任何错误输出

Gotype by default in the form of source code with go release, we need to manually compile it into the available tools, the compilation steps are as follows:

$cd $GOROOT/src/go/types$go build gotype.go在当前目录下就会看到gotype可执行文件,你可以将其mv or cp到$GOBIN下,方便在命令行中使用。

Second, Go toolchain (tool chain)

The powerful utility of Go's toolchain is no doubt, and the part that lets fans of other programming languages drool. Every go major version Release,go tool chain will be a big or small improvement, and this time it's no exception.

1. SSA

The SSA (Static single-assignment), which is unfamiliar to most developers and does not need to be cared for, only the compiler's talent will seriously study what it is. For the Go language user, the SSA means making the compiled application smaller, running faster, and having more space for optimization in the future, all without the need for go developers to modify even a single line of code ^_^.

In the Go core team's initial plan, the SSA should have joined when go 1.6, but due to the short development cycle of the go 1.6, the main SSA developer, Keith Randall, failed to complete the relevant development on time, especially in the performance issue, and failed to achieve the previously set goals. So the merge was postponed to go 1.7. Even go 1.7,ssa is the first to complete the x86-64 system.
To be honest, the introduction of the SSA backend, the risk is quite large, so go in the compiler added a switch "-ssa=0|1″, you can let developers choose whether to compile to the SSA backend, by default, the SSA backend is open under the X86-64 platform. At the same time, go 1.7 also modifies the format of the metadata for the package export, replaced by a shorter, refined binary format from the previous text format, which also makes the size of the resulting file of the go compilation more small.

We can simply test the effect of the above two optimizations on the post-compilation results by compiling the github.com/bigwhite/gocmpp/examples/client/example:

-rwxrwxr-x 1 share share 4278888  6月 20 14:20 client-go16*-rwxrwxr-x 1 share share 3319205  6月 20 14:04 client-go17*-rwxrwxr-x 1 share share 3319205  6月 20 14:05 client-go17-no-newexport*-rwxrwxr-x 1 share share 3438317  6月 20 14:04 client-go17-no-ssa*-rwxrwxr-x 1 share share 3438317  6月 20 14:03 client-go17-no-ssa-no-newexport*其中:client-go17-no-ssa是通过下面命令行编译的:$go build -a -gcflags="-ssa=0" github.com/bigwhite/gocmpp/examples/clientclient-go17-no-newexport*是通过下面命令行编译的:$go build -a -gcflags="-newexport=0" github.com/bigwhite/gocmpp/examples/clientclient-go17-no-ssa-no-newexport是通过下面命令行编译的:$go build -a -gcflags="-newexport=0 -ssa=0" github.com/bigwhite/gocmpp/examples/client

In contrast to client-go16 and client-go17, we can see that the executable program (CLIENT-GO17) compiled by Go 17, by default, is about 21% smaller than the program (CLIENT-GO16) compiled by Go 1.6, and the effect is obvious. This is also consistent with the official go-to-file size reduction 20%~30%de average effect.

However, comparing client-go17 and client-go17-no-newexport, we found that-newexport=0 did not seem to play a role, and the size of the two final executables was the same. This is the result of testing on Ubuntu 14.04 and Darwin platforms, and no solution.

When the SSA is introduced, the official argument is that the performance of the program will increase 5%~35%, the data from the official benchmark data, and the test will not be repeated here.

2. Compiler compiler performance

Go 1.5 Since the release of the go compiler performance has been greatly reduced by the go fans of the "criticism", although the performance of Go compiler and other programming languages are still "one of the leading." At worst, the build time for Go 1.5 was 4 times times more than the Go 1.4.x version. This issue also caused the Golang boss Rob Pike of great concern, in Russ Cox Planning go 1.7, Rob Pike asked to optimize the performance of Go compiler&linker, so there is go 1.7 "universal optimization" The go compiler and linker hundreds of commits, at least for the time being, have a noticeable effect.

Go big God Dave Cheney built three Benchmark:benchjuju, Benchkube, and benchgogs to track the compiler performance of Go 1.7 in development. Dave's latest performance comparison, last month, shows that compiling the same project, the go 1.7 compiler takes only about half of go 1.6, and go 1.4.3 is twice times faster than the go 1.7, which means that the go 1.6 has been improved by up to a factor of the build performance, from Go The 1.4.3 still has a one-fold gap.

3, StackFrame Pointer

On the eve of the Go 1.7 feature freeze, Russ Cox added stackframe pointer to go 1.7 in order to make tools like Linux perf or Intel VTune more efficient in crawling the go stack's tracking information. But the introduction of stackframe pointer will have some performance costs, around 2%. You can turn off this feature by setting the following environment variable:

export GOEXPERIMENT=noframepointer

4, CGO increase c.cbytes

CGO's helper functions are becoming richer, and this time the CGO increase c.cbytes helper function is derived from the needs of developers. Here is no longer to repeat the CGO of these helper function how to use, through a little bit of code perceptual understanding can:

// go17-examples/gotoolchain/cgo/print.gopackage main// #include 
  
   
    
   // #include 
   
    
     
    //// void print(void *array, int len) {//  char *c = (char*)array;////  for (int i = 0; i < len; i++) {//      printf("%c", *(c+i));//  }//  printf("\n");// }import "C"import "unsafe"func main() {    var s = "hello cgo"    csl := C.CBytes([]byte(s))    C.print(csl, C.int(len(s)))    C.free(unsafe.Pointer(csl))}执行该程序:$go run print.gohello cgo
   
    
  
   

5. Other minor changes

    • The go vendor mechanism, which passes the go 1.5 and go 1.6 experiments, will formally remove the go15vendorexperiment environment variable switch in Go 1.7 and use vendor as the default mechanism.
    • Go get supports git.openstack.org import path.
    • The Go Tool dist List command prints all the system and hardware architectures that go supports, and outputs the results on my machine as follows:
$go tool dist listandroid/386android/amd64android/armandroid/arm64darwin/386darwin/amd64darwin/armdarwin/arm64dragonfly/amd64freebsd/386freebsd/amd64freebsd/armlinux/386linux/amd64linux/armlinux/arm64linux/mips64linux/mips64lelinux/ppc64linux/ppc64lelinux/s390xnacl/386nacl/amd64p32nacl/armnetbsd/386netbsd/amd64netbsd/armopenbsd/386openbsd/amd64openbsd/armplan9/386plan9/amd64plan9/armsolaris/amd64windows/386windows/amd64

Three, standard library

1. Support Subtests and Sub-benchmarks

Table-driven testing is a best practice for Golang built-in testing framework, based on the idea of table-driven testing, Go 1.7 Further improved the testing organizational system, adding subtests and Sub-benchmarks. The goal is to achieve the following features:

    • The external command line (go test–run=xx) allows you to select a test or benchmark from a table for debugging purposes;
    • Simplify the writing of a set of similar benchmarks;
    • Using the Fail series method in subtest (e.g. failnow,skipnow, etc.);
    • Create subtests based on external or dynamic tables;
    • Finer-grained setup and teardown control, not just the testmain provided;
    • more parallel control;
    • The subtests and Sub-benchmark codes are more clean than the top-level functions for test and benchmark.

Here is an example based on the demo adaptation in the subtests documentation:

The traditional go-table-driven test is like Testsuminoldway in the following code:

// go17-examples/stdlib/subtest/foo_test.gopackage fooimport (    "fmt"    "testing")var tests = []struct {    A, B int    Sum  int}{    {1, 2, 3},    {1, 1, 2},    {2, 1, 3},}func TestSumInOldWay(t *testing.T) {    for _, tc := range tests {        if got := tc.A + tc.B; got != tc.Sum {            t.Errorf("%d + %d = %d; want %d", tc.A, tc.B, got, tc.Sum)        }    }}

For this traditional table-driven test, we can only measure the level of control granularity at the top level, that is, Testsuminoldway:

$go test --run=TestSumInOldWayPASSok      github.com/bigwhite/experiments/go17-examples/stdlib/subtest    0.008s

At the same time, in order to make it easier to discern which group of data is causing the problem in case fail, Errorf the output with some test data, such as in the above code: "%D+%D=%D; Want%d ".

If implemented through subtests, we can refine the granularity of control to the subtest level. And since Subtest itself has the subtest name uniqueness, there is no need to take that set of test data in error:

// go17-examples/stdlib/subtest/foo_test.gofunc assertEqual(A, B, expect int, t *testing.T) {    if got := A + B; got != expect {        t.Errorf("got %d; want %d", got, expect)    }}func TestSumSubTest(t *testing.T) {    //setup code ... ...    for i, tc := range tests {        t.Run("A=1", func(t *testing.T) {            if tc.A != 1 {                t.Skip(i)            }            assertEqual(tc.A, tc.B, tc.Sum, t)        })        t.Run("A=2", func(t *testing.T) {            if tc.A != 2 {                t.Skip(i)            }            assertEqual(tc.A, tc.B, tc.Sum, t)        })    }    //teardown code ... ...}

We deliberately modified the sum value of the third set of test data in the tests array to make it easier to compare the test results:

var tests = []struct {    A, B int    Sum  int}{    {1, 2, 3},    {1, 1, 2},    {2, 1, 4},}

Execution Testsumsubtest:

$go test --run=TestSumSubTest--- FAIL: TestSumSubTest (0.00s)    --- FAIL: TestSumSubTest/A=2#02 (0.00s)        foo_test.go:19: got 3; want 4FAILexit status 1FAIL    github.com/bigwhite/experiments/go17-examples/stdlib/subtest    0.007s

Perform the two subtest of "A=1″" and "A=2″" respectively:

$go test --run=TestSumSubTest/A=1PASSok      github.com/bigwhite/experiments/go17-examples/stdlib/subtest    0.007s$go test --run=TestSumSubTest/A=2--- FAIL: TestSumSubTest (0.00s)    --- FAIL: TestSumSubTest/A=2#02 (0.00s)        foo_test.go:19: got 3; want 4FAILexit status 1FAIL    github.com/bigwhite/experiments/go17-examples/stdlib/subtest    0.007s

The results of the test verify the two points mentioned earlier:
1, the output of subtest with unique identification, such as: "Fail:testsumsubtest/a=2#02 (0.00s)"
2, we can refine the control granularity to subtest level.

From the form of the code, subtest supports grouping of test data, such as the above test to divide testsum into a=1 and a=2 two groups, so as to separate control and result comparison separately.

In addition, because the control granularity supports the subtest layer, setup and teardown are no longer limited to the testmain level, and developers can add setup and subtest to teardown in each top-level test function. , the approximate pattern is as follows:

func TestFoo(t *testing.T) {    //setup code ... ...    //subtests... ...    //teardown code ... ...}

The subtest in Go 1.7 also supports concurrent execution:

func TestSumSubTestInParalell(t *testing.T) {    t.Run("blockgroup", func(t *testing.T) {        for _, tc := range tests {            tc := tc            t.Run(fmt.Sprint(tc.A, "+", tc.B), func(t *testing.T) {                t.Parallel()                assertEqual(tc.A, tc.B, tc.Sum, t)            })        }    })    //teardown code}

The two-layer subtest is nested here, and the three sub-tests in the "Blockgroup" sub-test are executed in parallel with each other (Paralell) until the three sub-tests are executed, and the run of the Blockgroup sub-test is returned. The execution of other parallel test function (if any) in Testsumsubtestinparalell and Foo_test.go is sequential.

Sub-benchmark is similar to subtest in form and usage, and is not mentioned here.

2. Context Package

Go 1.7 moved the original Golang.org/x/net/context package into the standard library and placed it under $goroot/src/context, which is clearly due to the extensive use of the context model, and the Go core team responds to the community's voice, This is also the need of the go core team itself. In the Std Lib, net, net/http, os/exec all use the context. For a detailed description of the Context, there is no better than one "go Concurrent patterns:context" from Go team.

Iv. Other changes

Runtime is rarely used by a common developer, and is typically used by Go core team. It's worth noting that go 1.7 adds a runtime. Error (interface), all runtime-induced panic, its panic value not only implements the standard error interface, but also implements the runtime. Error interface.

Golang's GC continues to be polished and optimized by Austin Clements and Rick Hudson in version 1.7.

The execution efficiency of the Go 1.7 compiled program is increased by an average of 5%-35% (on the x86-64 platform) due to the introduction of SSAS and GC optimizations. Some of the standard library packages have been significantly optimized, such as: CRYPTO/SHA1, crypto/sha256, Encoding/binary, FMT, Hash/adler32, Hash/crc32, HASH/CRC64, image/ Color, Math/big, StrConv, strings, Unicode, and unicode/utf16, performance improvements above 10%.

Go 1.7 also adds experimental support for using binary package (non-source) build programs (for some consideration of commercial software release patterns), but the go core team is obviously reluctant to go too far in this area and does not commit to complete toolchain support.

Some of the other minor changes in the standard library can be found in the Go 1.7 release notes.

The example code that is covered in this article can be downloaded here.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.