golang通道内存使用是否动态?

golang通道内存使用是否动态?,go,Go,我测试了go通道内存使用情况,发现它与通道输入频率不同,而Goroutine的数量相同 正如下面的代码所示,我创建了数千个goroutine,它们向自己的通道生成数据,并使用来自同一通道的数据 通过仅更改producer的变量“interval”,我可以通过使用命令“top”进行监视来查看虚拟内存和驻留内存的变化 间隔越短,内存的使用量就越大 有人知道发生了什么吗 package main import ( "fmt" "os" "os/signal" "sys

我测试了go通道内存使用情况,发现它与通道输入频率不同,而Goroutine的数量相同

正如下面的代码所示,我创建了数千个goroutine,它们向自己的通道生成数据,并使用来自同一通道的数据

通过仅更改producer的变量“interval”,我可以通过使用命令“top”进行监视来查看虚拟内存和驻留内存的变化

间隔越短,内存的使用量就越大

有人知道发生了什么吗

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

type Session struct {
    KeepAlive chan bool
}

var count = 1024 * 8 * 4

var interval = 250 * time.Millisecond //3718.0m 3.587g   1.2m S 224.0 23.1

// var interval = 500 * time.Millisecond //2011.2m 1.923g   1.2m S 118.8 12.4

// var interval = 1 * time.Second   //1124.0m 1.059g   1.1m S  73.0  6.8

func main() {

    var gracefulStop = make(chan os.Signal, 1)
    signal.Notify(gracefulStop, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)

    for i := 0; i < count; i++ {
        go Loop()
    }

    <-gracefulStop
    fmt.Println("gracefulStop")
}

func Loop() (err error) {

    var se *Session
    se = NewSession()

    se.Serve()

    return
}

func NewSession() (s *Session) {

    fmt.Println("NewSession")

    s = &Session{

        KeepAlive: make(chan bool, 1),
    }

    return
}

func (s *Session) Serve() {

    fmt.Println("Serve")

    go s.sendLoop()

    s.readLoop()

    s.Close()

    return
}

func (s *Session) Close() {

    close(s.KeepAlive)
    fmt.Println("Close")
}

// local-------------------------------------------------------

func (s *Session) readLoop() {
    fmt.Println("readLoop")

    sec := time.Duration(1 * time.Minute)

ServerHandlerLoop:
    for {
        select {

        case alive := <-s.KeepAlive:
            if alive == false {
                break ServerHandlerLoop
            }

        case <-time.After(sec):
            fmt.Println("Timeout")
            break ServerHandlerLoop

        }
    }

    fmt.Println("readLoop EXIT")
}

func (s *Session) sendLoop() {

    for {

        s.KeepAlive <- true

        time.Sleep(interval)

    }

    s.KeepAlive <- false

    fmt.Println("ReadMessage EXIT")
}
主程序包
进口(
“fmt”
“操作系统”
“操作系统/信号”
“系统调用”
“时间”
)
类型会话结构{
陈波
}
变量计数=1024*8*4
var间隔=250*时间。毫秒//3718.0m 3.587g 1.2m S 224.0 23.1
//var间隔=500*时间。毫秒//2011.2m 1.923g 1.2m S 118.8 12.4
//var间隔=1*时间秒//1124.0m 1.059g 1.1m S 73.0 6.8
func main(){
var gracefulStop=make(通道操作信号,1)
signal.Notify(gracefulStop、syscall.SIGTERM、syscall.SIGINT、syscall.SIGKILL)
对于i:=0;i
import _ "net/http/pprof"

func main() {
    go func() { log.Fatal(http.ListenAndServe(":4000", nil)) }()

    //...
}
程序运行时,请运行pprof工具查看有关程序的各种统计信息。由于您关心内存使用情况,因此堆配置文件(正在使用的内存)可能是最相关的

$ go tool pprof -top 10 http://localhost:4000/debug/pprof/heap
Fetching profile over HTTP from http://localhost:4000/debug/pprof/heap
File: foo
Build ID: 10
Type: inuse_space
Time: Dec 21, 2018 at 12:52pm (CET)
Showing nodes accounting for 827.57MB, 99.62% of 830.73MB total
Dropped 9 nodes (cum <= 4.15MB)
      flat  flat%   sum%        cum   cum%
  778.56MB 93.72% 93.72%   796.31MB 95.86%  time.NewTimer
   18.25MB  2.20% 95.92%    18.25MB  2.20%  time.Sleep
   17.75MB  2.14% 98.05%    17.75MB  2.14%  time.startTimer
      11MB  1.32% 99.38%       11MB  1.32%  runtime.malg
       2MB  0.24% 99.62%   798.31MB 96.10%  main.(*Session).readLoop
         0     0% 99.62%   798.31MB 96.10%  main.(*Session).Serve
         0     0% 99.62%    18.25MB  2.20%  main.(*Session).sendLoop
         0     0% 99.62%   800.81MB 96.40%  main.Loop
         0     0% 99.62%    11.67MB  1.40%  runtime.mstart
         0     0% 99.62%    11.67MB  1.40%  runtime.newproc.func1
         0     0% 99.62%    11.67MB  1.40%  runtime.newproc1
         0     0% 99.62%    11.67MB  1.40%  runtime.systemstack
         0     0% 99.62%   796.31MB 95.86%  time.After

试试看,哎哟,我甚至没有注意到计时器占用了这么多内存。我非常感谢pprof的引入,它在监控程序状态方面有很大帮助。只是要明确一点:计时器单独占用的内存不是很多,但如果你创建了近800万个计时器,那么它就加起来了。
type Session struct {
    KeepAlive chan struct{}
}

func (s *Session) readLoop() {
    fmt.Println("readLoop")

    d := 1 * time.Minute
    t := time.NewTimer(d)

loop:
    for {
        select {
        case _, ok := <-s.KeepAlive:
            if !ok {
                break loop
            }

            if !t.Stop() {
                <-t.C
            }
            t.Reset(d)

        case <-t.C:
            fmt.Println("Timeout")
            break loop
        }
    }

    fmt.Println("readLoop EXIT")
}

func (s *Session) sendLoop() {
    defer close(s.KeepAlive)

    for {
        s.KeepAlive <- struct{}{}
        time.Sleep(interval)
    }
}