Logging GoLang数据记录器(带宽)内存泄漏
我正试图找到内存泄漏,我已经将其归零到代码的这一部分,但我找不到内存泄漏的位置或如何修复它,当我让一些人研究它时,他们建议它与这里提到的股票代码有关: 它漏了。有关于修复的想法吗 谢谢Logging GoLang数据记录器(带宽)内存泄漏,logging,go,Logging,Go,我正试图找到内存泄漏,我已经将其归零到代码的这一部分,但我找不到内存泄漏的位置或如何修复它,当我让一些人研究它时,他们建议它与这里提到的股票代码有关: 它漏了。有关于修复的想法吗 谢谢 package main import ( "bufio" "encoding/csv" "fmt" "log" "os" "time" ) // Records information about a transfer window: the total am
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次。滴答答,从不停止他们,并开始2个永不返回的goroutines。每次调用measureBandwidth都会泄漏这些资源
因为你已经有了一个你只在上面接收的频道,你应该用它作为一个信号从计数goroutine返回。然后调用方将关闭返回的通道以进行清理
第二个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
}
例如:
次要的挑剔,通常更倾向于使用有符号类型来操作这样的数值:参见此处的一个对话:您的代码未编译:抱歉,它是更大项目的一部分,这只是引用的代码的一部分,因此没有主函数我不知道使用它的上下文,但是measureBandwidth创建了两个永不停止的标记器,并启动了两个永不返回的goroutine。如果您反复调用它,您将泄漏这些资源。@JimB我们运行它是为了做带宽记录,它是通过函数调用的,所以是的,它们经常被调用;然而,我将如何着手解决这个问题呢?