Go Memory

1,566 views
1,385 views

Published on

Published in: Technology, Education
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,566
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
29
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Go Memory

  1. 1. Understanding Go Memory September 11, 2013 John Graham-Cumming www.cloudflare.com!
  2. 2. Allocation Primitives •  new(T)! •  Allocates memory for item with type T! •  Zeroes it zeroed ret = runtime·mallocgc(typ->size, flag, 1, 1);! ! •  make(T)! •  Allocates memory for item with type T! •  Initializes it •  Needed for channels, maps and slices •  Memory comes from internal heap www.cloudflare.com!
  3. 3. Two memory freeing processes •  Garbage collection •  Determines which blocks of memory are no longer used •  Marks areas of heap so they can be reused by your program •  Scavenging •  Determines when parts of the heap are idle for a long time •  Returns memory to the operation system www.cloudflare.com!
  4. 4. Garbage collection •  Controlled by the GOGC environment variable •  And by debug.SetGCPercentage()! // Initialized from $GOGC. GOGC=off means no gc.! //! // Next gc is after we've allocated an extra amount of! // memory proportional to the amount already in use.! // If gcpercent=100 and we're using 4M, we'll gc again! // when we get to 8M. This keeps the gc cost in linear! // proportion to the allocation cost. Adjusting gcpercent! // just changes the linear constant (and also the amount of! // extra memory used).! •  Default is same as GOGC=100! •  Can set GOGC=off or debug.SetGCPercentage(-1) (no garbage collection at all) www.cloudflare.com!
  5. 5. Scavenging •  Runs once per minute // If we go two minutes without a garbage collection, ! // force one to run.! forcegc = 2*60*1e9;! ! // If a span goes unused for 5 minutes after a garbage! // collection, we hand it back to the operating system.! limit = 5*60*1e9;! •  Can also force return of all unused memory by calling debug.FreeOSMemory()! www.cloudflare.com!
  6. 6. Memory Statistics •  Read with runtime.ReadMemStats(&m)
 ! •  The MemStats struct has tons of members •  Useful ones for looking at heap •  HeapInuse - # bytes in the heap allocated to things •  HeapIdle - # bytes in heap waiting to be used •  HeapSys - # bytes obtained from OS •  HeapReleased - # bytes released to OS www.cloudflare.com!
  7. 7. Test garbage making program func makeBuffer() []byte { ! return make([]byte, rand.Intn(5000000)+5000000) }! ! func main() { ! pool := make([][]byte, 20)! ! makes := 0 ! for { ! b := makeBuffer()
 makes += 1! ! i := rand.Intn(len(pool))! pool[i] = b! ! time.Sleep(time.Second)! }! }! www.cloudflare.com! !
  8. 8. What happens www.cloudflare.com!
  9. 9. debug.FreeOSMemory()! www.cloudflare.com!
  10. 10. Use a buffered channel func main() {! pool := make([][]byte, 20)! idle:= make(chan []byte, 5)! ! makes := 0! for {! var b []byte! select {! case b = <-idle:! default:! makes += 1! b = makeBuffer()! }! ! ! ! ! i := rand.Intn(len(pool))! if pool[i] != nil {! select {! case idle<- pool[i]:! pool[i] = nil! default:! }! }! pool[i] = b! time.Sleep(time.Second)! }! } www.cloudflare.com!
  11. 11. select for non-blocking receive A buffered channel makes a simple queue idle:= make(chan []byte, 5)! ! select {! case b = <-idle:
 ! default:! Try to get from the makes += 1! idle queue b = makeBuffer()! }! Idle queue empty? Make a new buffer www.cloudflare.com!
  12. 12. select for non-blocking send A buffered channel makes a simple queue idle:= make(chan []byte, 5)! ! select {! case buffer <- pool[i]:! pool[i] = nil! ! Try to return buffer default:! to the idle queue }! Idle queue full? GC will have to deal with the buffer www.cloudflare.com!
  13. 13. What happens www.cloudflare.com!
  14. 14. More realistic: 20 goroutines func main() {! pool := make([][]byte, 200)! ! for i := 0; i < 10; i++ {! go func(offset int) {! for {! b := makeBuffer()! j := offset+rand.Intn(20)! pool[j] = b! ! time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))! }! }(i*20)! }! }! www.cloudflare.com!
  15. 15. What happens www.cloudflare.com!
  16. 16. Shared across goroutines func main() {! buffer := make(chan []byte, 5)! ! pool := make([][]byte, 200)! for i := 0; i < 10; i++ {! go func(offset int) {! for {! var b []byte! select {! case b = <-buffer:! default: b = makeBuffer()! }! j := offset+rand.Intn(20)! if pool[j] != nil {! select {! case buffer <- pool[j]: pool[j] = nil! default:! }! }! pool[j] = b! time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))! }! }(i*20)! }! ! www.cloudflare.com!
  17. 17. What Happens www.cloudflare.com!
  18. 18. More realistic example •  Alter code to •  Always try to give back a random buffer from the pool •  50% of the time get a new one •  Should create more garbage www.cloudflare.com!
  19. 19. Idle length 5 www.cloudflare.com!
  20. 20. Idle length 20 www.cloudflare.com!
  21. 21. Idle length 50 www.cloudflare.com!
  22. 22. Also •  This works for things other than []byte •  Can be done with arbitrary types •  Just need some way to reset •  There’s a proposal to add something like this to the Go package library •  sync.Cache •  Follow TODO www.cloudflare.com!

×