第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang 通道內(nèi)存使用是動態(tài)的嗎?

golang 通道內(nèi)存使用是動態(tài)的嗎?

Go
有只小跳蛙 2023-05-22 15:56:51
我測試了 go channel 內(nèi)存使用情況,發(fā)現(xiàn)它與 channel 輸入頻率不同,而 goroutines 的數(shù)量是相同的。正如下面的代碼,我創(chuàng)建了數(shù)千個 goroutine,它們將數(shù)據(jù)生成到自己的通道并使用來自同一通道的數(shù)據(jù)。通過僅更改生產(chǎn)者的變量“間隔”,我可以通過使用命令“top”進行監(jiān)視來看到虛擬內(nèi)存和常駐內(nèi)存也發(fā)生變化。并且間隔越短,內(nèi)存的使用就越大。有誰知道會發(fā)生什么?package mainimport (    "fmt"    "os"    "os/signal"    "syscall"    "time")type Session struct {    KeepAlive chan bool}var count = 1024 * 8 * 4var 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.8func 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")}
查看完整描述

1 回答

?
青春有我

TA貢獻1784條經(jīng)驗 獲得超8個贊

pprof可以告訴你在哪里花費了內(nèi)存。只需為net/http/pprof包添加一個導(dǎo)入語句,并使用 http.DefaultServeMux 啟動一個 HTTP 服務(wù)器:

import _ "net/http/pprof"


func main() {

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


? ? //...

}

在程序運行時,運行 pprof 工具來查看有關(guān)程序的各種統(tǒng)計信息。由于您關(guān)心內(nèi)存使用情況,因此堆配置文件(使用中的內(nèi)存)可能是最相關(guān)的。


$ 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

time.Timer不出所料,您創(chuàng)建的大量stime.After占用了幾乎所有正在使用的內(nèi)存。

想一想:使用 250 毫秒的時間間隔,您創(chuàng)建計時器的速度比使用 1 秒的時間間隔快 4 倍。然而,計時器的壽命與間隔不成比例——它恒定為 60 秒。因此,在任何給定時間點,您有 4*60=240 倍以上的計時器處于活動狀態(tài)。

來自 time.After 的文檔:

等待持續(xù)時間過去后,然后在返回的通道上發(fā)送當(dāng)前時間。它等同于 NewTimer(d).C。在計時器觸發(fā)之前,垃圾收集器不會回收底層計時器。如果效率是一個問題,請改用 NewTimer 并在不再需要計時器時調(diào)用 Timer.Stop。

因此,為每個創(chuàng)建一個計時器readLoop并重新使用它。您可以通過使用空結(jié)構(gòu)值通道而不是布爾值通道來進一步減少內(nèi)存使用:

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)

? ? }

}


查看完整回答
反對 回復(fù) 2023-05-22
  • 1 回答
  • 0 關(guān)注
  • 147 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號