gpt4 book ai didi

logging - GoLang 数据记录器(带宽)内存泄漏

转载 作者:数据小太阳 更新时间:2023-10-29 03:42:32 25 4
gpt4 key购买 nike

我试图找到内存泄漏,我已将其归零到这部分代码,但我找不到内存泄漏的位置或如何修复它,当我让一些人调查时他们建议它与此处提到的“代码”有关: https://golang.org/src/time/tick.go它“泄漏”。关于修复有什么想法吗?

谢谢! :)

package main

import (
"bufio"
"encoding/csv"
"fmt"
"log"
"os"
"time"
)

// Records information about a transfer window: the total amount of data
// transferred in a fixed time period in a particular direction (clientbound or
// serverbound) in a session.
type DataLoggerRecord struct {
// Number of bytes transferred in this transfer window.
Bytes uint
}

var DataLoggerRecords = make(chan *DataLoggerRecord, 64)

// The channel returned should be used to send the number of bytes transferred
// whenever a transfer is done.
func measureBandwidth() (bandwidthChan chan uint) {
bandwidthChan = make(chan uint, 64)
timer := time.NewTicker(config.DL.FlushInterval * time.Second)

go func() {
for _ = range timer.C {
drainchan(bandwidthChan)
}
}()

go func() {
var count uint
ticker := time.Tick(config.DL.Interval)

for {
select {
case n := <-bandwidthChan:
count += n

case <-ticker:
DataLoggerRecords <- &DataLoggerRecord{
Bytes: count,
}
count = 0
}
}
}()

return bandwidthChan
}

func drainchan(bandwidthChan chan uint) {
for {
select {
case e := <-bandwidthChan:
fmt.Printf("%s\n", e)
default:
return
}
}
}


func runDataLogger() {
f, err := os.OpenFile(dataloc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("[DL] Could not open %s", err.Error())
}

bw := bufio.NewWriter(f)
defer func() {
bw.Flush()
f.Close()
}()

go func() {
for {
time.Sleep(time.Second)
bw.Flush()
}
}()

w := csv.NewWriter(bw)


for record := range DataLoggerRecords {
if record.Bytes != 0 {
err = w.Write([]string{
fmt.Sprintf("%d", record.Bytes),
})
w.Flush()
} else {
continue
}
}
if err != nil {
if err.Error() != "short write" {
log.Printf("[DL] Failed to write record: %s", err.Error())
} else {
w.Flush()
}
}
}

最佳答案

您正在启动 2 个 time.Ticker 并且从不停止它们,并且启动了 2 个永不返回的 goroutine。每次调用 measureBandwidth 时,您都会“泄漏”这些资源。

由于您已经有了一个仅用于接收的 channel ,因此您应该将其用作从计数 goroutine 返回的信号。然后,调用者将关闭返回的 channel 以进行清理。

第二个 goroutine 不是必需的,它只用于与计数器赛跑以丢弃值。计数 goroutine 可以跟上,如果发送到记录器的速度太慢,请将其放在自己的 select case 中。

func measureBandwidth() (bwCh chan int) {
bwCh = make(chan int, 64)

go func() {
ticker := time.NewTicker(config.DL.Interval)
defer ticker.Stop()

count := 0

for {
select {
case n, ok := <-bwCh:
if !ok {
return
}
count += n

case <-ticker.C:
DataLoggerRecords <- &DataLoggerRecord{Bytes: count}
count = 0
}
}
}()

return bwCh
}

示例:http://play.golang.org/p/RfpBxPlGeW

(小吹毛求疵,通常首选使用带符号的类型来操作数值,如下所示:请参阅此处的此类对话:When to use unsigned values over signed ones?)

关于logging - GoLang 数据记录器(带宽)内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35880960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com