Monthly Archives: November 2013

A Go client for Joyent Manta

Over the last few weeks I had the opportunity of working with the Joyent folks on the port of Go to Solaris1.

As part of this work I noted that the Joyeurs were using their rather spiffy Manta service for sharing code snippets and build logs. This made the rest of us using Pastebin services feel rather Web 1.0.

So, last weekend I sat down and wrote a simple Manta client in Go. As of this morning the total line count including tests was less than 450 lines. I don’t know how that compares to the Node.js or Java clients, but i’d be willing to bet it is far shorter thanks to the utility of the Go standard library.

Code is on github, https://github.com/davecheney/manta. Also included are implementations of some of the Manta CLI utilities.

Docs are on godoc, http://godoc.org/github.com/davecheney/manta


  1. Our port is actually called sunos/amd64 partly because Aram and I are nostalgic curmudgeons, but mainly because the OS X port of Go is called darwin.

Benchmarking Go 1.2rc5 vs gccgo

I’ve been doing a lot of work with gccgo recently and with the upcoming release of Go 1.2 I’ve also been collecting benchmark results for that release.

Presented below, using a very unscientific method, are the results of comparing the go1 benchmark results for the two compilers.

gc-vs-gccgo

Buried among that see of red are a few telltale signs that the more capable gcc backed optimiser can eek out better arithmetic performance.

As another data point, here is the floats benchmark from my autobench suite, run under the same conditions as above.

floats

I want to be clear that these are very preliminary results, and, like all all micro benchmarks are subject to interpretation.

I also want to stress that I am not dismissing gccgo based on these results. As I understand it gccgo lacks a few key features, such as escape analysis, which is probably responsible for most of the performance loss when the amount of computation is dwarfed by memory bookkeeping.

gccgo is developed largely by one person, ian Taylor, and is a significant achievement. Recently he and Chris Manghane have been working on decoupling the gofrontend code from gcc so it can be reused with other compiler backends, LLVM being the most obvious.

If you are interested in contributing to Go, please don’t forget about gccgo, or even llgo as possible outlets for your energies. Go itself is a stronger language because we have at least four implementations of the specification. This helps keep the compiler writers honest and avoids the language being defined by default by its most popular implementation.

Evaluation order oddity

At Canonical we’re increasingly invested in gccgo. While testing various packages built with gccgo we ran across test failures which we traced to an innocent looking piece of code.

package main

import "fmt"

type T struct {
        i int
}

func (t *T) readInt32() int32 {
        t.i += 4
        return 42 // not important
}

func main() {
        var d = T{i:200}
        end := d.i - 4 + int(d.readInt32())
        fmt.Println(end)
}

So, knowing that the Go spec defines the order of evaluation of functions calls and assignments as left to right, let’s try to predict what this code will print.

200 - 4 + 42 = 238

So, is 238 the correct answer ?

% go run odd.go 
242

Wow, that is odd. Let’s see what gccgo thinks the answer is

% go run -compiler gccgo odd.go 
238

Well, at least it got the right answer, so is gc at fault or are the arguments actually evaluated in the opposite direction ?

It turns out that both compilers are correct because the evaluation order of this sort of expression is not specified. In fact, in the spec, this case is called out in an example which is strongly reminiscent of the original code.

a := 1
f := func() int { a = 2; return 3 }
x := []int{a, f()}  // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified

The correct solution to this problem is to break the expression into two lines, removing the ambiguity about when the addition to d.i is visible.

func main() {
        var d = T{i:200}
        v := int(d.readInt32())
        end := v + d.i - 4
        fmt.Println(end) 	// prints 242
}

More simple test coverage in Go 1.2

In a previous post I blogged about the cover tool coming in Go 1.2 and a bash helper function I use to make the tool a little easier to use.

Since then I’ve extended these helpers so I wanted to blog about the improvements.

Passing arguments to the testing tool

cover () {
  t=$(tempfile)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -func=$t && unlink $t
}

The first improvement is to be able to pass arguments to go test, this is done by setting COVERFLAGS before invoking the cover helper.

As an example, I have defined a flag in the sftp package tests that allow me to switch the integration tests on and off.

% cover github.com/pkg/sftp
PASS
coverage: 20.4% of statements
...
 % COVERFLAGS=-integration cover github.com/pkg/sftp 
PASS
coverage: 69.2% of statements
...

Viewing coverage details

The cover in its default mode will give you a percentage coverage on a per function basis, but it doesn’t tell you which parts of the function are uncovered.

cover-web() {
  t=$(tempfile)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -html=$t && unlink $t
}

To explore the coverage report in detail, this helper runs the cover tool then opens a web browser with a html version of the coverage report.

Screenshot from 2013-11-14 15:50:59Enjoy!

Stupid Go declaration tricks

This is a brief post highlighting a curious aspect of the declaration syntax in Go.

Most Go programmers know that the following of import declarations are equivalent

import "fmt"
import "math/big"

// same as
import (
        "fmt"
        "math/big"
)

The same applies to const declarations

const FORTYTWO = 42
const TRUE = 1

// same as
const (
        FORTYTWO = 42
        TRUE     = 1
)

But perhaps you didn’t know that the syntax is also valid for type declarations. For example, the following is valid syntax in Go.

type (
        B struct{ a, b int }
        C interface {
                Hello() error
        }
)

However because the func declaration has been extended to place methods on types, the following is not valid syntax

func (
        main() {
                fmt.Println("wowzers")
        }
)

Subcommand handling in Go

A few days ago I was working on an example program for the sftp package and found I needed to implement subcommand handling.

https://twitter.com/davecheney/status/397686194462396416

The response was fantastic, no less than 12 different packages. I haven’t had the chance to review any of the packages in detail, but I wanted to list them here as thanks to the great #golang community,

https://twitter.com/bketelsen/status/398152055107624961

Calling for autobench contributions for Go 1.2

With the release of go1.2rc3 last week I have now merged the autobench-next branch into master in the autobench repository.

Go 1.2 is not expected to bring performance improvements of the same magnitude of Go 1.1, but moderate improvements are expected due to improvements in code generation, the runtime, the garbage collector, and the standard library.

If you would like to contribute a benchmark result from your own machine the instructions for doing so are included the README file.