2017-12-03 156 views
2

我发现奇怪占据堆时转换字节[]到字符串下面代码转换字节[],在golang串奇怪占据堆

package main 

import (
    "bytes" 
    "fmt" 
    "net/http" 
    _ "net/http/pprof" 
    "strings" 
    "time" 
) 

var (
    c = make(chan int, 500000) 
) 

func main() { 
    go func() { 
    http.ListenAndServe(":8080", nil) 
    }() 
    f := func(ss []string) { 
    fmt.Println(ss) 
    time.Sleep(time.Millisecond) 
    <-c 
    } 
    for { 
    c <- 1 
    bs := bytes.NewBufferString("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z").Bytes() 
    fmt.Println(bs) // will raise memory leak after marked as comment??? 
    s := string(bs) 
    ss := strings.Split(s, ",") 
    go f(ss) 
    } 
} 
  1. 而不fmt.Println(bs)将逐渐耗尽存储器。

  2. fmt.Println(bs)工作正常。我无法理解发生了什么?我与version go1.9.2 darwin/amd64

回答

4

没有工作,有没有内存泄漏:
您正在使用500000并发够程,你只需要限制(减少)并发够程的数量,例如:

c := make(chan int, runtime.NumCPU()) 

试试这个(看这个编辑的结尾):

package main 

import (
    "bytes" 
    "fmt" 
    "runtime" 
    "strings" 
    "time" 
) 

func main() { 
    c := make(chan int, runtime.NumCPU()) 
    for { 
     c <- 1 
     bs := bytes.NewBufferString("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z").Bytes() 
     s := string(bs) 
     ss := strings.Split(s, ",") 
     go func(ss []string) { 
      fmt.Println(ss) 
      time.Sleep(time.Millisecond) 
      <-c 
     }(ss) 
    } 
} 

代码:

package main 

import (
    "bytes" 
    "fmt" 
    "net/http" 
    _ "net/http/pprof" 
    "strings" 
    "time" 
) 

var (
    c = make(chan int, 500000) 
) 

func main() { 
    go func() { 
     http.ListenAndServe(":8080", nil) 
    }() 
    f := func(ss []string) { 
     fmt.Println(ss) 
     time.Sleep(time.Millisecond) 
     <-c 
    } 
    for { 
     c <- 1 
     bs := bytes.NewBufferString("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z").Bytes() 
     // fmt.Println(bs) // will raise memory leak after marked as comment??? 
     s := string(bs) 
     ss := strings.Split(s, ",") 
     go f(ss) 
    } 
} 

它一段时间后达到稳定状态,甚至减少内存使用:

// Mem   CPU time: 
// 5,464,208K 0:1:20 
// 5,468,208K 0:2:20 
// 5,469,608K 0:3:20 
// 5,469,844K 0:4:20 
// 5,469,844K 0:5:20 
// 5,469,848K 0:6:20 
// 5,469,848K 0:7:20 fixed 
// 5,469,848K 0:8:20 fixed 
// 5,469,616K 0:9:20 reduced 
+0

有尝试添加fmt.Println(BS)?那会减少内存占用 – Nelson

+0

我想知道 – Nelson

+0

是的,当然。使用'fmt.Println(bs)'可以让GC(垃圾回收器)有更多的时间来收集内存,而使用'fmt.Println(bs)'的内存使用量为'25520KBytes'。 –