在Go 1.3.1中获取可变内存使用情况

时间:2014-09-08 01:12:57

标签: go

  1. 为什么此代码无法找到内存使用量(m2-m1)和(m4-m3)?
  2. 为什么(m3-m2)和(m5-m4)需要分配额外的内存?
  3. Full code here

    type T struct {
        B uint8
        S string
        I int
    }
    
    func memUsage(mOld, mNew *runtime.MemStats) {
        fmt.Println("Alloc:", mNew.Alloc-mOld.Alloc,
            "HeapAlloc:", mNew.HeapAlloc-mOld.HeapAlloc,
            "TotalAlloc:", mNew.TotalAlloc-mOld.TotalAlloc)
    }
    func main() {
        var m1, m2, m3, m4, m5, m6 runtime.MemStats
        runtime.ReadMemStats(&m1)
        t := T{}
        runtime.ReadMemStats(&m2)
        fmt.Println(t)
        memUsage(&m1, &m2)
    
        runtime.ReadMemStats(&m3)
        t2 := "abc"
        runtime.ReadMemStats(&m4)
        fmt.Println(t2)
        memUsage(&m3, &m4)
    
        runtime.ReadMemStats(&m5)
        t3 := map[int]string{1: "x"}
        runtime.ReadMemStats(&m6)
        fmt.Println(t3)
        memUsage(&m5, &m6)
    
        memUsage(&m2, &m3)
        memUsage(&m4, &m5)
    }
    

    输出

    {0  0}
    Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
    abc
    Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
    map[1:x]
    Alloc: 256 HeapAlloc: 256 TotalAlloc: 256
    Alloc: 432 HeapAlloc: 432 TotalAlloc: 432
    Alloc: 64 HeapAlloc: 64 TotalAlloc: 64
    

1 个答案:

答案 0 :(得分:3)

变量t在堆栈上分配。

package main

import (
    "fmt"
)

type T struct {
    B uint8
    S string
    I int
}

func main() {
    t := T{}
    fmt.Println(t)
}

伪汇编:

0x0021 00033 (t.go:14)  LEAQ    "".statictmp_0002+0(SB),BX
0x0028 00040 (t.go:14)  LEAQ    "".t+88(SP),BP
0x002d 00045 (t.go:14)  MOVQ    BP,DI
0x0030 00048 (t.go:14)  MOVQ    BX,SI
0x0033 00051 (t.go:14)  DUFFCOPY    ,$

参考文献:

A Manual for the Plan 9 assembler


您已经大幅修改了您的问题。下次,问一个新问题。

你打电话给fmt包裹,使你的水域变得混乱。我们只能看到fmt包执行一些堆分配。我们必须追踪fmt包中的数百行代码,看看发生了什么。此外,结果不可重复。

我删除了所有的混乱:

package main

import (
    "fmt"
    "runtime"
)

type T struct {
    B uint8
    S string
    I int
}

func memUsage(mOld, mNew *runtime.MemStats) {
    fmt.Println("Alloc:", mNew.Alloc-mOld.Alloc,
        "HeapAlloc:", mNew.HeapAlloc-mOld.HeapAlloc,
        "TotalAlloc:", mNew.TotalAlloc-mOld.TotalAlloc)
}
func main() {
    var m1, m2, m3, m4, m5, m6, m7 runtime.MemStats
    runtime.ReadMemStats(&m1)
    t := T{}
    runtime.ReadMemStats(&m2)
    _ = t
    runtime.ReadMemStats(&m3)
    t2 := "abc"
    runtime.ReadMemStats(&m4)
    _ = t2
    runtime.ReadMemStats(&m5)
    t3 := map[int]string{1: "x"}
    runtime.ReadMemStats(&m6)
    _ = t3
    runtime.ReadMemStats(&m7)

    memUsage(&m1, &m2)
    memUsage(&m2, &m3)
    memUsage(&m3, &m4)
    memUsage(&m4, &m5)
    memUsage(&m5, &m6)
    memUsage(&m6, &m7)
}

输出:

Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0
Alloc: 256 HeapAlloc: 256 TotalAlloc: 256
Alloc: 0 HeapAlloc: 0 TotalAlloc: 0

除了创建使用堆栈和堆的映射之外,很容易看到堆栈的使用。

注意:Go内存管理依赖于实现。它经常得到改进,并且即将完全改写。