go - memory pooling and buffered channel with multiple goroutines -


i'm creating program create random bson.m documents, , insert them in database. main goroutine generate documents, , push them buffered channel. in same time, 2 goroutines fetch documents channel , insert them in database.

this process take lot of memory , put pressure on garbage colelctor, i'm trying implement memory pool limit number of allocations

here have far:

package main  import (     "fmt"     "math/rand"     "sync"     "time"      "gopkg.in/mgo.v2/bson" )  type list struct {     l []bson.m }  func main() {     var rndsrc = rand.newsource(time.now().unixnano())      pool := sync.pool{         new: func() interface{} {             l := make([]bson.m, 1000)             i, _ := range l {                 m := bson.m{}                 l[i] = m             }             return &list{l: l}         },     }     // buffered channel store generated bson.m docs     var record = make(chan list, 3)    // start worker insert docs in database       := 0; < 2; i++ {         go func() {             r := range record {                 fmt.printf("first: %v\n", r.l[0])                 // insert ect              }         }()     }     // feed channel      := 0; < 100; i++ {         // object pool instead of creating new 1          list := pool.get().(*list)         // re generate documents          j, _ := range list.l {             list.l[j]["key1"] = rndsrc.int63()         }         // push docs channel, , return them pool           record <- *list         pool.put(list)     } } 

but looks 1 list used 4 times before being regenerated:

> go run test.go first: map[key1:943279487605002381 key2:4444061964749643436] first: map[key1:943279487605002381 key2:4444061964749643436] first: map[key1:943279487605002381 key2:4444061964749643436] first: map[key1:943279487605002381 key2:4444061964749643436] first: map[key1:8767993090152084935 key2:8807650676784718781] ... 

why isn't list regenerated each time ? how can fix ?

the problem have created buffered channel var record = make(chan list, 3). hence code:

record <- *list pool.put(list) 

may return , entry placed pool before has been consumed. hence underlying slice modified in loop iteration before consumer has had chance consume it. although sending list value object, remember []bson.m pointer allocated array , still pointing same memory when send new list value. hence why seeing duplicate output.

to fix, modify channel send list pointer make(chan *list, 3) , change consumer put entry in pool once finished, e.g:

for r := range record {     fmt.printf("first: %v\n", r.l[0])     // insert etc     pool.put(r) // if error occurs } 

your producer should sent pointer pool.put removed, i.e.

record <- list 

Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -