From "Lessons Learned Optimizing NSQ"
- avoid []byte to string conversions
- re-use buffers or objects (use sync.Pool in Go 1.3)
- pre-allocate slices make([]byte, 0, 1024)
- explicitly specify number/size of items on the wire
- leave nothing unbounded
- apply sane limits to configurable dials (message size, # of messages)
- avoid boxing (use of interface{}) or unnecessary wrapper types
- avoid the use of defer in hot code paths (it allocates)
don’t be afraid of the sync package
- channels are overkill for primitives
- goroutines are cheap not free (~4k per)
- use worker pools rather than “goroutine per X”
- synchronizing goroutine exit and cleanup is hard
- all IO must have timeouts (guarantee progress)
- wrap IO with bufio.Reader/Writer to reduce context switches (syscalls)
- select skips nil channels