golang memory analysis

Just like C/C++, it's very straightforward to analyze memory usage in Go.  But since Go compiler has GC and escape analysis, the memory layout looks a little complicate. Let's start from a simple code snippet.


package main

import (
    "fmt"
)

type mem struct {
    block [1024 * 1024]byte
}
type pmem *mem

var gmem *mem = new(mem)

func stackmem(m mem) {
    fmt.Printf("  func local:%p", &m)
}

func main() {

    const ITEMS = int(10)
    mps := make([]pmem, ITEMS)
    fmt.Printf("global: %p  alloc for global:%p main:%p\n", &gmem, gmem, main)
    for c := 0; c < ITEMS; c++ {
        /*
            var mp mem
            fmt.Printf("local mp: %p", &mp)

            go func(m *mem) {
                fmt.Printf("   routine local:%p", &m)
            }(&mp)
            stackmem(mp)
        */
        mps[c] = new(mem)

        fmt.Printf("  local: %p  alloc:%p\n", &mps[c], mps[c])

    }

}

At first we commented out func and goroutine as above, the output would be:

F:\go\samples>go run mem.go
global: 0x5acad0  alloc for global:0xc08204a000 main:0x401040
  local: 0xc08200c1e0  alloc:0xc08214c000
  local: 0xc08200c1e8  alloc:0xc08224c000
  local: 0xc08200c1f0  alloc:0xc08234c000
  local: 0xc08200c1f8  alloc:0xc082456000
  local: 0xc08200c200  alloc:0xc08255e000
  local: 0xc08200c208  alloc:0xc082662000
  local: 0xc08200c210  alloc:0xc08276e000
  local: 0xc08200c218  alloc:0xc08286e000
  local: 0xc08200c220  alloc:0xc08296e000
  local: 0xc08200c228  alloc:0xc082a6e000

Obviously, as usual,  the code/text/global segment layouts as OS loading at lower address space.   the layout for stack/heap is not so clear, but for now, all new() returns continuous address space.

Let's comment out only the goroutine as below:

func main() {

    const ITEMS = int(10)
    mps := make([]pmem, ITEMS)
    fmt.Printf("global: %p  alloc for global:%p main:%p\n", &gmem, gmem, main)
    for c := 0; c < ITEMS; c++ {

        var mp mem
        fmt.Printf("local mp: %p", &mp)
        stackmem(mp)
        /*
            go func(m *mem) {
                fmt.Printf("   routine local:%p", &m)
            }(&mp)
        */

        mps[c] = new(mem)

        fmt.Printf("  local: %p  alloc:%p\n", &mps[c], mps[c])

    }

}

The  output looks like:

F:\go\samples>go run mem.go
global: 0x5b9ad0  alloc for global:0xc08204a000 main:0x401140
local mp: 0xc08214a000  func local:0xc082544000  local: 0xc08200c1e0  alloc:0xc082644000
local mp: 0xc082756000  func local:0xc082864000  local: 0xc08200c1e8  alloc:0xc082544000
local mp: 0xc08214a000  func local:0xc082864000  local: 0xc08200c1f0  alloc:0xc08296c000
local mp: 0xc082a6c000  func local:0xc082864000  local: 0xc08200c1f8  alloc:0xc082754000
local mp: 0xc082b6c000  func local:0xc082c6c000  local: 0xc08200c200  alloc:0xc082a6c000
local mp: 0xc08285c000  func local:0xc08214a000  local: 0xc08200c208  alloc:0xc082d6c000
local mp: 0xc082e6c000  func local:0xc082f6c000  local: 0xc08200c210  alloc:0xc08306c000
local mp: 0xc08316c000  func local:0xc082f6c000  local: 0xc08200c218  alloc:0xc08285c000
local mp: 0xc08214a000  func local:0xc082b6c000  local: 0xc08200c220  alloc:0xc082c6c000
local mp: 0xc08326c000  func local:0xc08336c000  local: 0xc08200c228  alloc:0xc08316c000

Things look complicated now, it's not easy to discriminate stack/heap allocation just like C/C++.  where  heap/stack boundary is clear...





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章