Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Experiences building InfluxDB with #golang

Paul Dix
September 24, 2014

Experiences building InfluxDB with #golang

Tech talk given at #greetech06 in Tokyo

Paul Dix

September 24, 2014
Tweet

More Decks by Paul Dix

Other Decks in Technology

Transcript

  1. Experiences Building InfluxDB with #golang Paul Dix CEO of InfluxDB

    http://influxdb.com paul@influxdb.com @pauldix
  2. Scala def binarySearch[A <% Ordered[A]](! a: IndexedSeq[A], v: A) =

    {! ! def recurse(low: Int, ! high: Int): Option[Int] = (low + high) / 2 match {! ! case _ if high < low => None! case mid if a(mid) > v => recurse(low, mid - 1)! case mid if a(mid) < v => recurse(mid + 1, high)! case mid => Some(mid)! }! recurse(0, a.size - 1)! }!
  3. Go func binarySearch(! a []float64, value float64, low int, high

    int) int {! ! if high < low {! return -1! }! mid := (low + high) / 2! if a[mid] > value {! return binarySearch(a, value, low, mid-1)! } else if a[mid] < value {! return binarySearch(a, value, mid+1, high)! }! return mid! }!
  4. We use goraft. There were many times we wasted a

    day troubleshooting a bug introduced from “go get” against a dependency when building on a new server.
  5. Create a vendor directory in your project and import from

    there. Read more here: https://bitly.com/greetech06_vendoring
  6. Channels of Channels // Execute event loop for the given

    state.! l.ch = make(chan chan struct{})! ! switch state {! case Follower:! go l.followerLoop(l.ch)! case Candidate:! go l.candidateLoop(l.ch)! case Leader:! go l.leaderLoop(l.ch)! }! }! From Ben Johnson’s Streaming Raft: https://github.com/influxdb/influxdb/blob/streaming-raft/raft/log.go
  7. // in the loop! for {! // Check if the

    loop has been closed.! select {! case ch := <-done:! close(ch)! return! default:! }! ! // do stuff ! }!
  8. func (l *Log) setState(state State) {! // Stop previous state.!

    if l.ch != nil {! ch := make(chan struct{})! l.ch <- ch! <-ch! l.ch = nil! }! ! // restart loop! }!
  9. Time series data is many small objects. In testing we

    saw significant GC pauses with heaps as small as 2GB.
  10. ! // allocate slab! ! slabSize := 1024! ! b,

    _ := syscall.Mmap(-1, 0, slabSize,! ! ! syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC,! ! ! syscall.MAP_ANON|syscall.MAP_PRIVATE)! ! ! // store values! ! someVals := []float64{23, 92, 1, 0, 3}! ! offset := 0! ! for _, v := range someVals {! ! ! x := (*float64)(unsafe.Pointer(&b[offset]))! ! ! *x = v! ! ! offset += 8! ! }! ! ! // read them out! ! offset = 0! ! for offset < len(b) {! ! ! x := (*float64)(unsafe.Pointer(&b[offset]))! ! ! offset += 8! ! ! fmt.Println("n: ", *x)! ! }!
  11. No keep alive timeouts so we do this type HttpServer

    struct {! // ...! readTimeout time.Duration! // ...! }! ! // later we create the server with timeout! srv := &http.Server{! Handler: p, ReadTimeout: h.readTimeout}!
  12. Timeout Problems • GC Pauses • Large Requests • Overloaded

    network • Slow server • All occur under load
  13. Timeout Problems • GC Pauses • Large Requests • Overloaded

    network • Slow server • All occur under load • All lead to connection flapping
  14. Read more here: http://bit.ly/greetech06_slice type point struct {! val float64!

    time time.Time! }! ! func leakMemory() []*point {! points := make([]*point, 0)! // make some points! for i := 0; i < 1000; i++ {! points = append(! points, &point{float64(i), time.Now()})! }! // all points still kept in memory!! return points[10:20]! }!
  15. Slices of structs is fast to allocate, lower GC overhead.

    Slices of pointers is faster to move around and sort.
  16. Benchmark Against Go Source for Reference go test -bench=. <pkg>

    For example: - 20ns for Mutex lock/unlock - 70ns for RWMutex lock/unlock - json encodes at 100MB/s - json decodes at 25MB/s
  17. InfluxDB still has work to do to use what we

    have learned since September 2013