亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

在 for 循環中使用數據庫連接時出現內存泄漏

在 for 循環中使用數據庫連接時出現內存泄漏

Go
蕭十郎 2023-08-14 16:56:28
我正在嘗試在無限 for 循環中連續查詢 Postgres 數據庫。但是,查詢似乎沒有關閉,垃圾收集器可能無法工作,并且我面臨內存分配問題。腳本設計如下:在func main()我聲明一個全局數據庫連接。然后執行func checkCross(...)其中包含 for 循環,每次迭代都會執行該循環,func importPrices(...)然后從數據庫導入行。import (    "database/sql"    _"github.com/lib/pq"    "runtime"    )var db *sql.DBfunc main() {    var err error    psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+" dbname=%s password=%s ", host, port, user, dbname, password)    //connection    db, err = sql.Open("postgres", psqlInfo)    if err != nil {        log.Fatal(err)    }    defer db.Close()    checkCross("EUR_USD")    ...函數 checkCross(...)   func checkCross(instrument string) {    for i := 1; i < 4; i++ {            rawData, _ := importPrices(instrument)            var mem runtime.MemStats            runtime.ReadMemStats(&mem)            fmt.Printf("alloc [%v] \t heapAlloc [%v] \n", mem.Alloc, mem.HeapAlloc)            ...        }函數導入價格(...)func importPrices(instrument string) ([]float64, []time.Time) {    var price_ float64    var date_ time.Time    price := make([]float64, 10000000)    date := make([]time.Time, 10000000)    queryCommand := fmt.Sprintf("SELECT * FROM table where instrument = '%[1]v' ORDER BY 1 ASC;", instrument)    rows, err := db.Query(queryCommand)    if err != nil {        log.Fatal(err)    }    //scan from db    z := 0    for rows.Next() {        err := rows.Scan(&date_, &price_)        if err != nil {            log.Fatal(err)        }        price[z] = price_        date[z] = date_        z+=1    }    price = price[:z]     date = date[:z]     if err := rows.Err(); err != nil {        log.Fatal(err)    }    rows.Close()    return price, date輸出alloc [321664064]        heapAlloc [321664064] alloc [641723264]        heapAlloc [641723264] alloc [961781984]        heapAlloc [961781984]您能否指導我的代碼或方法中的問題出在哪里?rows.Close()我讀過一些文章,他們建議在 for 循環中使用,defer rows.Close()但這個解決方案不起作用。
查看完整描述

1 回答

?
守著一只汪

TA貢獻1872條經驗 獲得超4個贊

您在每次調用時分配兩個 10M 元素的切片(float648 字節并且更大) 。time.TimeimportPrices

當然,這些切片中的大多數最終都會變成垃圾(據說,您用從 返回的那兩個切片覆蓋了一些變量importPrices),但這些垃圾會自然浮動,直到為您的程序提供支持的 Go 運行時決定收集它。在此之前,內存消耗將會增加。

理解該語言的兩種“標準”實現(您應該使用其中一種)功能掃描GC 與主程序流并行工作是至關重要的。換句話說,當程序丟失對已分配內存塊的最后一個實時引用時,該塊占用的內存在那一刻不會發生任何事情- 它必須等到 GC 找到它并進行收集。這種情況發生的確切時間大多是無法預測的。Go 具有復雜的動態算法來調整GC 的速度,從而在收集垃圾所花費的 CPU 周期數量和讓內存消耗增長之間取得一定的平衡。

對于當前的問題,通常的方法是簡單地重用迭代之間分配的內存。也就是說,在調用之前預先分配切片importPrices,將它們傳遞到那里,然后將它們重置為零長度,然后再次傳遞它們。


查看完整回答
反對 回復 2023-08-14
  • 1 回答
  • 0 關注
  • 163 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號