亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

記一次python 內(nèi)存泄漏問(wèn)題及解決過(guò)程

 更新時(shí)間:2018年11月29日 08:21:47   作者:python修行路  
最近工作中慢慢開(kāi)始用python協(xié)程相關(guān)的東西,所以用到了一些相關(guān)模塊,如aiohttp, aiomysql, aioredis等,用的過(guò)程中也碰到的很多問(wèn)題,這里整理了一次內(nèi)存泄漏的問(wèn)題。分享到腳本之家平臺(tái),需要的朋友參考下

最近工作中慢慢開(kāi)始用python協(xié)程相關(guān)的東西,所以用到了一些相關(guān)模塊,如aiohttp, aiomysql, aioredis等,用的過(guò)程中也碰到的很多問(wèn)題,這里整理了一次內(nèi)存泄漏的問(wèn)題

通常我們寫(xiě)python程序的時(shí)候也很少關(guān)注內(nèi)存這個(gè)問(wèn)題(當(dāng)然可能我的能力還有待提升),可能寫(xiě)c和c++的朋友會(huì)更多的考慮這個(gè)問(wèn)題,但是一旦我們的python程序出現(xiàn)了

內(nèi)存泄漏的問(wèn)題,也將是一件非常麻煩的事情了,而最近的一次代碼中也碰到了這個(gè)問(wèn)題,不過(guò)好在最后內(nèi)存溢出不是我代碼的問(wèn)題,而是所用到的一個(gè)包出現(xiàn)了內(nèi)存的問(wèn)題,下面我通過(guò)一個(gè)簡(jiǎn)單的代碼模擬出內(nèi)存的問(wèn)題,然后也會(huì)將解決的過(guò)程描述一下,希望能幫助到遇到同樣問(wèn)題的朋友。

一、復(fù)現(xiàn)問(wèn)題

其實(shí)這次主要是在使用aiohttp寫(xiě)一個(gè)接口的時(shí)候出現(xiàn)的問(wèn)題,其實(shí)復(fù)現(xiàn)出問(wèn)題非常容易,我們實(shí)現(xiàn)一個(gè)簡(jiǎn)單的接受post請(qǐng)求接口的服務(wù)端,然后實(shí)現(xiàn)一個(gè)并發(fā)的客戶端來(lái)訪問(wèn)這個(gè)接口,來(lái)查看內(nèi)存的情況

注意: 這個(gè)問(wèn)題是在一個(gè)包的特定版本出現(xiàn)的:multidict==4.5.1,我在整理這個(gè)文章2個(gè)小時(shí)前作者已經(jīng)修復(fù)了這個(gè)問(wèn)題發(fā)布了4.5.2版本,已經(jīng)修復(fù)了內(nèi)存的問(wèn)題,并且我也進(jìn)行了測(cè)試驗(yàn)證

服務(wù)端代碼:

from aiohttp import web
async def hello(request):
 return web.json_response(await request.json())
app = web.Application()
app.add_routes([web.post('/', hello)])
web.run_app(app)

客戶端代碼:

import asyncio
import aiohttp
async def foo(times):
 data = {'foo': 1}
 async with aiohttp.ClientSession() as session:
  for x in range(times):
   resp = await session.post('http://localhost:8080', json=data)
   if not x % 100:
    print(await resp.json())
loop = asyncio.get_event_loop()
loop.run_until_complete(foo(100000))
loop.close()

因?yàn)槲业拇a是在linux上跑的,或者mac上我們都可以通過(guò)htop非常方面的實(shí)時(shí)查看我們程序內(nèi)存的占用情況,我們先將服務(wù)端啟動(dòng),查看一下我們此時(shí)的內(nèi)存情況可以看到占用的

非常少,當(dāng)我們打開(kāi)客戶端之后,再次觀察我們可以看到內(nèi)存不斷增長(zhǎng),及時(shí)我們客戶端運(yùn)行完畢內(nèi)存也不會(huì)降低。

 當(dāng)客戶端結(jié)束之后的內(nèi)存:

如果客戶端不停止的話內(nèi)存會(huì)一直漲,最后的結(jié)果就是把你的系統(tǒng)內(nèi)存吃完,然后被系統(tǒng)殺掉你的進(jìn)程。

二、解決內(nèi)存泄漏的過(guò)程

像上面的例子是一個(gè)非常簡(jiǎn)單的程序,不復(fù)雜我們也并沒(méi)有做上面復(fù)雜的操作就是一個(gè)簡(jiǎn)單的接受post請(qǐng)求的服務(wù)端,但是如果是在實(shí)際的項(xiàng)目中我們可能會(huì)寫(xiě)非常復(fù)雜的業(yè)務(wù)邏輯,那到時(shí)候我們又如何找到是哪里導(dǎo)致的內(nèi)存問(wèn)題,當(dāng)我碰到這個(gè)問(wèn)題的時(shí)候,其實(shí)我和很多接觸python不久的人差不多,也是不知道怎么查這種問(wèn)題,各種百度各種查,也找到了好多推薦的工具,memory_profiler庫(kù),objgraph庫(kù),graphviz工具,但是都沒(méi)有幫助我迅速的找到問(wèn)題點(diǎn)在哪里,最后看到標(biāo)準(zhǔn)庫(kù)中的tracemalloc,地址:https://docs.python.org/3/library/tracemalloc.html

通過(guò)這個(gè)包很快幫我找到了內(nèi)存泄漏的地方

接下來(lái)按照官網(wǎng)的方法我將代碼進(jìn)行改寫(xiě),來(lái)測(cè)試到底哪里的問(wèn)題導(dǎo)致的內(nèi)存泄漏,更改后的服務(wù)端代碼為:

from aiohttp import web
import tracemalloc
async def hello(request):
 return web.json_response(await request.json())
async def get_info(request):
 snapshot2 = tracemalloc.take_snapshot()
 top_stats = snapshot2.compare_to(snapshot1, 'lineno')
 print(top_stats)
 return web.Response(text="ok")
if __name__ == '__main__':
 app = web.Application()
 app.add_routes(
  [
   web.post('/', hello),
   web.get("/get_info", get_info)
  ]
 )
 tracemalloc.start()
 snapshot1 = tracemalloc.take_snapshot()
 web.run_app(app)

注意print(top_stats)這行打印的結(jié)果最后要關(guān)注

 其實(shí)這里就是新增加了一個(gè)路由get_info, 我們啟動(dòng)服務(wù)端之后開(kāi)啟客戶端,當(dāng)我們客戶端運(yùn)行完畢之后,可以看到內(nèi)存已經(jīng)漲上去了,并且沒(méi)有不會(huì)釋放,這個(gè)時(shí)候,可以直接通過(guò)瀏覽器訪問(wèn)get_info這個(gè)路由看看print打印的內(nèi)容,這里將會(huì)打印出你程序運(yùn)行到這個(gè)時(shí)候那一行的代碼內(nèi)存增長(zhǎng)的比較多,進(jìn)行一次排序,前面的幾個(gè)其實(shí)都是需要你關(guān)注的,因?yàn)檫@里數(shù)據(jù)較多,我就只打印如下前幾個(gè)數(shù)據(jù)

<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=56>,)> size=116500672 (+116500672) count=300004 (+300004)>,
<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=604>,)> size=11400000 (+11400000) count=200000 (+200000)>, 
<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=472>,)> size=8000000 (+8000000) count=100000 (+100000)>, 
<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=353>,)> size=5500000 (+5500000) count=100000 (+100000)>, 
<StatisticDiff traceback=<Traceback (<Frame filename='/Users/zhaofan/anaconda3/lib/python3.6/site-packages/aiohttp/web_response.py' lineno=352>,)> size=5300608 (+5300608) count=100001 (+100001)>,

我們拿第一行來(lái)說(shuō),我們可以非常清楚的指導(dǎo)web_response的56行代碼導(dǎo)致內(nèi)存增長(zhǎng)的最多,當(dāng)然如果是我們復(fù)雜的項(xiàng)目也可以通過(guò)類似的方法,這樣就可以非??旖莸恼业轿覀兇a中哪些地方會(huì)造成內(nèi)存溢出,便于排查問(wèn)題,我們點(diǎn)進(jìn)去看看這行代碼:

我們找到最終行,這個(gè)時(shí)候我們大致就可以看出哪里的問(wèn)題了,我們接著看  CIMultiDict

class CIMultiDict(MultiDict):
 def _title(self, key):
  return key.title()

我們可以看到這個(gè)它繼承  MultiDict 其實(shí)這里我們已經(jīng)應(yīng)該知道問(wèn)題就是處在這個(gè)MultiDict上了

而這個(gè)最終其實(shí)最終就是MultiDict這個(gè)包,問(wèn)題出在了這個(gè)包上,這個(gè)項(xiàng)目是在這里維護(hù)的:https://github.com/aio-libs/multidict

查看這個(gè)包的時(shí)候看到了,果然有人和我遇到了同樣的問(wèn)題,問(wèn)題就是出在這里了,已經(jīng)有人提交了bug

https://github.com/aio-libs/multidict/issues/307

不過(guò)不得不說(shuō)國(guó)外的程序員真的是熱愛(ài)自己的職業(yè),很快這個(gè)問(wèn)題得到了aio-libs小組中人的回應(yīng),問(wèn)題也在我整理這個(gè)博客的時(shí)候被修復(fù)了,在最新的版本:4.5.2中已經(jīng)測(cè)試沒(méi)有內(nèi)存泄漏的問(wèn)題

三、總結(jié)

在這里處理的過(guò)程中,其實(shí)發(fā)現(xiàn)了自己很多的不足,查找問(wèn)題的方式,以及遇到這種問(wèn)題的解決思路,不過(guò)經(jīng)過(guò)這次,至少下次遇到同樣的問(wèn)題,自己能很快的去查找

以及解決問(wèn)題,還有就是針對(duì)https://docs.python.org/3/library/tracemalloc.html這個(gè)庫(kù)的使用,也推薦大家多了解一下。

以上所述是小編給大家介紹的記一次python 內(nèi)存泄漏問(wèn)題及解決過(guò)程,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持

相關(guān)文章

  • Python traceback模塊獲取異常信息的使用

    Python traceback模塊獲取異常信息的使用

    Python的traceback模塊提供了多種方法來(lái)獲取和展示異常的堆棧信息,本文主要介紹了Python traceback模塊獲取異常信息的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Python使用MD5加密字符串示例

    Python使用MD5加密字符串示例

    這篇文章主要介紹了Python使用MD5加密字符串示例,對(duì)一些可能出現(xiàn)的錯(cuò)誤點(diǎn)上本文也給出提醒,需要的朋友可以參考下
    2014-08-08
  • python socket模塊創(chuàng)建和使用套接字示例詳解

    python socket模塊創(chuàng)建和使用套接字示例詳解

    這篇文章主要為大家介紹了python socket模塊來(lái)創(chuàng)建和使用套接字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • python面積圖之曲線圖的填充

    python面積圖之曲線圖的填充

    這篇文章主要介紹了python面積圖之曲線圖的填充,文章圍繞主題的相關(guān)資料展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-06-06
  • pycharm 如何取消連按兩下shift出現(xiàn)的全局搜索

    pycharm 如何取消連按兩下shift出現(xiàn)的全局搜索

    這篇文章主要介紹了pycharm 如何取消連按兩下shift出現(xiàn)的全局搜索?下面小編就為大家介紹一下解決方法,還等什么?一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • Python ckeditor富文本編輯器代碼實(shí)例解析

    Python ckeditor富文本編輯器代碼實(shí)例解析

    這篇文章主要介紹了Python ckeditor富文本編輯器代碼實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • python文件數(shù)據(jù)分析治理提取

    python文件數(shù)據(jù)分析治理提取

    這篇文章主要介紹了python文件數(shù)據(jù)分析治理提取,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Python中的常用函數(shù)使用及說(shuō)明

    Python中的常用函數(shù)使用及說(shuō)明

    這篇文章主要介紹了Python中的常用函數(shù)使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Pycharm學(xué)習(xí)教程(6) Pycharm作為Vim編輯器使用

    Pycharm學(xué)習(xí)教程(6) Pycharm作為Vim編輯器使用

    這篇文章主要為大家詳細(xì)介紹了最全的Pycharm學(xué)習(xí)教程第六篇,Pycharm作為Vim編輯器使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Python OpenCV處理圖像之濾鏡和圖像運(yùn)算

    Python OpenCV處理圖像之濾鏡和圖像運(yùn)算

    這篇文章主要為大家詳細(xì)介紹了Python OpenCV處理圖像之濾鏡和圖像運(yùn)算,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評(píng)論