以下代碼聲明瞭兩個數組,然後迭代stdin(只是盲目地迭代文件 - 不與數組交互)。當聲明非常大的數組並迭代stdin時,golang會增加連續內存
這是造成內存不斷增加的原因。
但是,如果我只聲明兩個數組並睡眠 - 內存沒有增加。
同樣,如果我只是遍歷stdin - 內存沒有增加。
但是在一起(除了分配給陣列的內存之外)還在不斷增加。
我通過使用頂級工具查看RES內存來衡量這一點。
我已將func doSomething()
中的前幾行註釋掉,表明在註釋時沒有內存增加。取消註釋和運行會導致增加。
注意:您將需要至少16GB的RAM重新創建此一臺機器上,因爲我已經在只觀察到的那樣:這是在去1.4.2,1.5.3和1.6
注意運行陣列大小爲10億。
package main
import (
"bufio"
"fmt"
"io"
"os"
)
type MyStruct struct {
arr1 []int
arr2 []int
}
func (ms *MyStruct) Init(size int, arr1 []int, arr2 []int) error {
fmt.Printf("initializing mystruct arr1...\n")
ms.arr1 = arr1
if ms.arr1 == nil {
ms.arr1 = make([]int, size, size)
}
fmt.Printf("initializing mystruct arr2...\n")
ms.arr2 = arr2
if ms.arr2 == nil {
ms.arr2 = make([]int, size, size)
}
fmt.Printf("done initializing ...\n")
for i := 0; i < size; i++ {
ms.arr1[i] = 0
ms.arr2[i] = 0
}
return nil
}
func doSomething() error {
fmt.Printf("starting...\n")
fmt.Printf("allocating\n")
/* NOTE WHEN UNCOMMENTED CAUSES MEMORY INCREASE
ms := &MyStruct{}
size := 1000000000
ms.Init(size, nil, nil)
*/
fmt.Printf("finished allocating..%d %d\n", len(ms.arr1), len(ms.arr2))
fmt.Printf("reading from stdin...\n")
reader := bufio.NewReader(os.Stdin)
var line string
var readErr error
var lineNo int = 0
for {
if lineNo%1000000 == 0 {
fmt.Printf("read %d lines...\n", lineNo)
}
lineNo++
line, readErr = reader.ReadString('\n')
if readErr != nil {
fmt.Printf("break at %s\n", line)
break
}
}
if readErr == io.EOF {
readErr = nil
}
if readErr != nil {
return readErr
}
return nil
}
func main() {
if err := doSomething(); err != nil {
panic(err)
}
fmt.Printf("done...\n")
}
- 這是我的代碼的問題嗎?或者是去系統做一些意想不到的事情?
- 如果是後者,我該如何去調試呢?
爲了更容易在這裏複製是很好的情況下(上述代碼的註釋部分)和不好的情況下引擎收錄文件(取消註釋部分)
wget http://pastebin.com/raw/QfG22xXk -O badcase.go
yes "1234567890" | go run badcase.go
wget http://pastebin.com/raw/G9xS2fKy -O goodcase.go
yes "1234567890" | go run goodcase.go
你如何衡量「增加內存」以及你在討論哪種類型的內存。很可能一切都很好;瀏覽你的代碼看起來沒問題。當然,如果你分配20億的內存,你的代碼會消耗更多的內存,因爲這至少是8 GB。 – Volker
@Volker我啓動一個htop並監視RES內存。是的,在64位計算機上啓動時大約需要16 GB,但是當我從stdin開始閱讀時,它就會啓動並永不停止。 (更新了問題以反映評論)。 – algrebe
你確定它確實不停止嗎?要看看記憶,請遵循http://dave.cheney.net/2015/11/29/a-whirlwind-tour-of-gos-runtime-environment-variables,特別是GODEBUG和gctrace,它比(h )頂部 – Volker