偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

如何排查Python中的內(nèi)存問題?

譯文
開發(fā) 后端
內(nèi)存問題很難在Python中加以診斷和修復(fù)。本文介紹了如何使用流行的開源Python軟件包查明和修復(fù)內(nèi)存泄漏。

[[407502]]

【51CTO.com快譯】發(fā)現(xiàn)應(yīng)用程序內(nèi)存不足是開發(fā)者遇到的糟糕問題之一。內(nèi)存問題一般很難加以診斷和修復(fù),而在Python中尤為困難。Python的自動(dòng)垃圾收集讓您易于上手該語言,但出現(xiàn)問題時(shí),開發(fā)者不知道如何識(shí)別和修復(fù)問題。

本文介紹如何診斷和修復(fù)開源AutoML庫EvalML中的內(nèi)存問題。解決內(nèi)存問題沒什么訣竅,但我希望開發(fā)者、尤其是Python開發(fā)者可以了解將來遇到這類問題時(shí)可利用的工具和優(yōu)秀實(shí)踐。

什么是內(nèi)存泄漏?

任何編程語言最重要的功能之一是能夠?qū)⑿畔⒋鎯?chǔ)在計(jì)算機(jī)內(nèi)存中。每當(dāng)您的程序創(chuàng)建一個(gè)新變量,它都會(huì)分配一些內(nèi)存用于存儲(chǔ)該變量的內(nèi)容。

內(nèi)核為程序訪問計(jì)算機(jī)的CPU、內(nèi)存和磁盤存儲(chǔ)等資源定義了接口。每種編程語言提供了要求內(nèi)核分配和釋放內(nèi)存塊供運(yùn)行中的程序使用的方法。

程序要求內(nèi)核留出內(nèi)存塊供使用,但隨后由于錯(cuò)誤或崩潰,程序完成使用該內(nèi)存后從未告訴內(nèi)核,就會(huì)發(fā)生內(nèi)存泄漏。在這種情況下,內(nèi)核將繼續(xù)認(rèn)為被遺忘的內(nèi)存塊仍被運(yùn)行中的程序使用,其他程序無法訪問這些內(nèi)存塊。

如果運(yùn)行程序時(shí)同樣的泄漏一再發(fā)生,被遺忘的內(nèi)存總量會(huì)變得很龐大,因而消耗計(jì)算機(jī)的大部分內(nèi)存!在這種情況下,如果程序隨后嘗試請(qǐng)求更多內(nèi)存,內(nèi)核會(huì)拋出“內(nèi)存不足”錯(cuò)誤,程序?qū)⑼V惯\(yùn)行,換句話說“崩潰”。

因此,找到并修復(fù)所編寫的程序中的內(nèi)存泄漏很重要,否則程序最終可能會(huì)耗盡內(nèi)存并崩潰,或者可能導(dǎo)致其他程序崩潰。

第1步:確定是內(nèi)存問題

應(yīng)用程序崩潰的原因有很多:也許運(yùn)行代碼的服務(wù)器崩潰了,也許代碼本身存在邏輯錯(cuò)誤,所以確定眼前的問題是內(nèi)存問題很重要。

EvalML性能測(cè)試悄然崩潰。突然,服務(wù)器停止記錄進(jìn)度,作業(yè)悄然停止。服務(wù)器日志會(huì)顯示編程錯(cuò)誤引起的任何堆棧追蹤,所以我有預(yù)感:崩潰是作業(yè)耗用所有的可用內(nèi)存引起的。

我又重新進(jìn)行了性能測(cè)試,但這次啟用了Python的內(nèi)存分析器,以獲取內(nèi)存使用情況圖。測(cè)試再次崩潰,當(dāng)我查看內(nèi)存圖時(shí),發(fā)現(xiàn)了該圖:

圖1.性能測(cè)試的內(nèi)存使用情況

內(nèi)存使用情況逐漸保持穩(wěn)定,但隨后達(dá)到8 GB!我知道應(yīng)用服務(wù)器有8GB 的內(nèi)存,所以該圖證實(shí)我們耗盡了內(nèi)存。此外,內(nèi)存穩(wěn)定時(shí),我們使用約4 GB的內(nèi)存,但之前版本的EvalML使用約2 GB的內(nèi)存。由于某種原因,當(dāng)前版本使用的內(nèi)存是平常的大約兩倍。

現(xiàn)在需要找出原因。

第2步:用極簡(jiǎn)示例在本地重現(xiàn)內(nèi)存問題

查明內(nèi)存問題的原因需要大量實(shí)驗(yàn)和迭代,因?yàn)榇鸢竿ǔ2⒉幻黠@。如果是這樣,您可能不會(huì)將其寫入代碼!出于這個(gè)原因,我認(rèn)為用盡可能少的代碼行重現(xiàn)問題很重要。這個(gè)極簡(jiǎn)示例使您可以在修改代碼時(shí)在分析器下快速運(yùn)行它,查看是否取得進(jìn)展。

我憑經(jīng)驗(yàn)知道,大概在我看到大峰值時(shí),應(yīng)用程序運(yùn)行含有150萬行的出租車數(shù)據(jù)集。我將應(yīng)用程序精簡(jiǎn)至僅運(yùn)行該數(shù)據(jù)集的部分。我看到了類似上述的峰值,但這次內(nèi)存使用量達(dá)到了10 GB!

見此情形,我知道有一個(gè)足夠好的極簡(jiǎn)示例可深入研究。

圖2. 出租車數(shù)據(jù)集本地重現(xiàn)的內(nèi)存使用情況

第3步:找到分配最多內(nèi)存的代碼行

一旦將問題隔離到盡可能小的代碼塊,我們可以看到程序在何處分配最多的內(nèi)存。這便于您重構(gòu)代碼和修復(fù)問題。

filprofiler是個(gè)出色的Python工具。它顯示應(yīng)用程序中每一行代碼在內(nèi)存使用高峰時(shí)的內(nèi)存分配情況。這是本地示例的輸出結(jié)果:

圖3. fil-profile的輸出

filprofiler根據(jù)內(nèi)存分配情況對(duì)應(yīng)用程序中的代碼行(以及依賴項(xiàng)的代碼)進(jìn)行排名。線越長(zhǎng)越紅,分配的內(nèi)存越多。

分配最多內(nèi)存的代碼行用來創(chuàng)建pandas數(shù)據(jù)幀(pandas/core/algorithms.py和pandas/core/internal/managers.py),數(shù)據(jù)量達(dá)4GB!我在這里截?cái)嗔薴ilprofiler的輸出,但它能夠?qū)andas代碼追溯到用EvalML來創(chuàng)建Pandas數(shù)據(jù)幀的代碼。

是的,EvalML創(chuàng)建Pandas數(shù)據(jù)幀,但這些數(shù)據(jù)幀在整個(gè)AutoML算法中都是短暫的,一旦不再使用就應(yīng)該被釋放。由于實(shí)際情況并非如此,加上這些數(shù)據(jù)幀在內(nèi)存中的時(shí)間足夠長(zhǎng),我認(rèn)為最新版本帶來了內(nèi)存泄漏。

第4步:識(shí)別泄漏對(duì)象

在Python中,泄漏對(duì)象是使用完成后沒有被Python的垃圾收集器釋放的對(duì)象。由于 Python使用引用計(jì)數(shù)作為主要的垃圾收集算法之一,這些泄漏對(duì)象通常是由對(duì)象占有引用時(shí)間過長(zhǎng)引起的。

這類對(duì)象很難找到,但可以用一些Python工具簡(jiǎn)化搜尋。第一個(gè)工具是垃圾收集器的gc.DEBUG_SAVEALL標(biāo)志。若設(shè)置該標(biāo)志,垃圾收集器將無法訪問的對(duì)象存儲(chǔ)在gc.garbage列表中。這讓您可以進(jìn)一步研究這些對(duì)象。

第二個(gè)工具是objgraph庫。一旦對(duì)象在gc.garbage列表中,我們可以根據(jù)pandas數(shù)據(jù)幀過濾該列表,并使用objgraph查看哪些其他對(duì)象引用這些數(shù)據(jù)幀、將它們保存在內(nèi)存中。

這是我在可視化其中一個(gè)數(shù)據(jù)幀后看到的對(duì)象圖的一個(gè)子集:

圖4. Pandas數(shù)據(jù)幀使用內(nèi)存圖,顯示導(dǎo)致內(nèi)存泄漏的循環(huán)引用

這就是我要找的確鑿證據(jù)!數(shù)據(jù)幀通過創(chuàng)建循環(huán)引用的PandasTableAccessor對(duì)自身進(jìn)行引用,因此這會(huì)將對(duì)象保留在內(nèi)存中,直到Python的垃圾收集器運(yùn)行并釋放它。(可以通過dict、PandasTableAccessor、dict和_dataframe 追蹤循環(huán)。)這對(duì)EvalML來說有問題,因?yàn)槔占鲗⑦@些數(shù)據(jù)幀保存在內(nèi)存中的時(shí)間太長(zhǎng),以至于我們耗盡內(nèi)存!

我能夠?qū)andasTableAccessor追溯到Woodwork庫,并將該問題提交給維護(hù)者。他們?cè)谛掳姹局行迯?fù)后,向pandas存儲(chǔ)庫提交了相關(guān)的問題單,這個(gè)例子表明了開源生態(tài)系統(tǒng)中的合作。

Woodwork更新發(fā)布后,我可視化同一個(gè)數(shù)據(jù)幀的對(duì)象圖,循環(huán)消失了!

圖5.woodwork升級(jí)后pandas數(shù)據(jù)幀的對(duì)象圖。不再有循環(huán)!

第5步:驗(yàn)證修復(fù)是否有效

我在EvalML中升級(jí)Woodwork 版本后,測(cè)量了應(yīng)用程序的內(nèi)存使用情況。結(jié)果發(fā)現(xiàn),內(nèi)存使用量現(xiàn)在不到過去的一半!

圖6. 修復(fù)后性能測(cè)試的內(nèi)存使用情況

原文標(biāo)題:How to troubleshoot memory problems in Python,作者:Freddy Boulton

【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】

責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2013-03-27 10:32:22

2018-11-06 12:12:00

MySQL內(nèi)存排查

2021-02-26 13:35:46

JavaCPU內(nèi)存

2024-08-19 00:10:00

C++內(nèi)存

2022-07-03 20:31:59

JVMJava虛擬機(jī)

2015-07-20 10:23:24

NET內(nèi)存問題排查

2022-01-26 19:42:05

MySQL亂碼排查

2024-01-05 09:23:09

Linux系統(tǒng)內(nèi)存內(nèi)存指標(biāo)

2020-06-23 09:48:09

Python開發(fā)內(nèi)存

2018-08-10 15:00:42

服務(wù)器內(nèi)存排查

2019-12-17 10:01:40

開發(fā)技能代碼

2023-10-08 13:10:00

Redis數(shù)據(jù)庫

2019-01-04 08:00:59

Linux硬件容器

2019-04-29 14:23:46

Java服務(wù)器CPU

2014-02-27 13:30:26

CacheLinux系統(tǒng)內(nèi)存不足

2022-04-11 15:10:34

微服務(wù)遷移goroutine

2021-07-30 20:59:21

MySQL內(nèi)存.參數(shù)

2024-11-21 16:47:55

2023-10-13 12:05:55

RedisBig Key

2022-05-13 23:46:52

GO編程內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)