日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

监视Rails进程内存泄漏的技巧

發(fā)布時(shí)間:2023/12/31 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 监视Rails进程内存泄漏的技巧 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Rails應(yīng)用比較容易遇到的兩類性能問(wèn)題:一類是Rails執(zhí)行很慢,CPU消耗過(guò)高;另一類是Rails進(jìn)程內(nèi)存泄漏。解決這兩類問(wèn)題都需要你首先能夠精確定位出現(xiàn)問(wèn)題的代碼,然后才知道如何對(duì)癥下藥。?

一、如何監(jiān)控Rails進(jìn)程的執(zhí)行性能?

定位消耗CPU高,執(zhí)行速度緩慢的Rails代碼,是相當(dāng)容易的事情,僅僅需要你對(duì)production.log做一點(diǎn)統(tǒng)計(jì)分析,抽取出來(lái)執(zhí)行時(shí)間最長(zhǎng)的請(qǐng)求,問(wèn)題就昭然若揭了。由于production.log對(duì)Rails請(qǐng)求的執(zhí)行時(shí)間做了詳細(xì)的統(tǒng)計(jì),例如:?

Ruby代碼??
  • Completed?in?0.00693?(144?reqs/sec)?|?Rendering:?0.00489?(70%)?|?DB:?0.00000?(0%)?|?200?OK?[http://www.iteye.com/]??
  • Completed?in?0.17238?(5?reqs/sec)?|?Rendering:?0.10011?(58%)?|?DB:?0.06244?(36%)?|?200?OK?[http://www.iteye.com/topic/49441?page=7]??
  • Completed?in?0.20508?(4?reqs/sec)?|?Rendering:?0.19373?(94%)?|?DB:?0.00645?(3%)?|?200?OK?[http://www.iteye.com/news/1586]??


  • 所以我們只需要寫一行shell命令,就搞定了!他把最耗時(shí)的前500個(gè)請(qǐng)求篩選出來(lái),保存到timing.log里面。?

    Ruby代碼??
  • grep?"200?OK"?production.log?|?awk?'{print?"ALL:?"?$3?"??View:?"?$8?"?DB:?"?$12?"??URL:?"?$17?}'?\??
  • |?sort?-r?|?head?-n?500?>?timing.log??


  • 排序好的結(jié)果例如:?

    Ruby代碼??
  • ALL:?5.51774??View:?5.38277?DB:?0.13338??URL:?[http://www.iteye.com/wiki/topic/131966]??
  • ALL:?5.51316??View:?5.31300?DB:?0.19400??URL:?[http://www.iteye.com/wiki/topic/145383]??
  • ALL:?5.51311??View:?5.39321?DB:?0.11234??URL:?[http://www.iteye.com/wiki/topic/160370]??
  • ALL:?5.51135??View:?5.37604?DB:?0.12652??URL:?[http://www.iteye.com/wiki/topic/233365]??
  • ALL:?5.49881??View:?5.35998?DB:?0.10637??URL:?[http://www.iteye.com/wiki/topic/265217]??


  • 哪些請(qǐng)求執(zhí)行的慢,一目了然。 當(dāng)然除此之外,我們還可以實(shí)時(shí)監(jiān)控,在top監(jiān)視窗口顯示Rails當(dāng)前正在執(zhí)行的請(qǐng)求URL?

    二、如何監(jiān)控Rails進(jìn)程的內(nèi)存泄漏?

    監(jiān)控CPU是很容易的事情,但要監(jiān)控Rails進(jìn)程的內(nèi)存泄漏,卻非常困難,原因在于production.log里面并沒(méi)有記錄進(jìn)程的內(nèi)存變化狀況,甚至你找不到任何ruby API可以用來(lái)直接查詢到進(jìn)程使用的物理內(nèi)存。實(shí)際上,要獲取一個(gè)進(jìn)程的物理內(nèi)存是一個(gè)平臺(tái)相關(guān)的操作,每個(gè)操作系統(tǒng)都會(huì)自己特定的API,并不通用,即使用C語(yǔ)言來(lái)編碼,也不是一件容易的事情。?

    不過(guò)對(duì)于Linux操作系統(tǒng)來(lái)說(shuō),我們有一個(gè)捷徑可以獲取進(jìn)程的內(nèi)存狀況。Linux的/proc文件系統(tǒng)是內(nèi)核的映象,/proc/進(jìn)程pid/status 文件記錄了這個(gè)進(jìn)程的狀態(tài)信息,例如:?

    Ruby代碼??
  • Name:???dispatch.fcgi??
  • State:??S?(sleeping)??
  • SleepAVG:???????135%??
  • Tgid:???26645??
  • Pid:????26645??
  • PPid:???1??
  • TracerPid:??????0??
  • Uid:????1002????1002????1002????1002??
  • Gid:????100?????100?????100?????100??
  • FDSize:?64??
  • Groups:?14?16?17?33?100???
  • VmSize:???245680?kB??
  • VmLck:?????????0?kB??
  • VmRSS:????209104?kB??
  • VmData:???205116?kB??
  • VmStk:???????824?kB??
  • VmExe:???????764?kB??
  • VmLib:??????4220?kB??
  • Threads:????????1??
  • SigPnd:?0000000000000000??
  • ShdPnd:?0000000000000000??
  • SigBlk:?0000000000000000??
  • SigIgn:?0000000000001000??
  • SigCgt:?0000000002006e47??
  • CapInh:?0000000000000000??
  • CapPrm:?0000000000000000??
  • CapEff:?0000000000000000??


  • 注意第14行VmRSS,記錄了該進(jìn)程使用的常駐物理內(nèi)存(Residence),這個(gè)就是該進(jìn)程實(shí)際占用的物理內(nèi)存了。因此只要我們讀取該文件第14行,就可以得到內(nèi)存信息。?

    所以我們的任務(wù)變成了:在Rails處理請(qǐng)求之前記錄內(nèi)存,等Rails處理完請(qǐng)求之后,再記錄內(nèi)存,計(jì)算內(nèi)存的變化狀況,寫入到production.log里面去。完成這個(gè)工作,只需要我們?cè)赗ails應(yīng)用的app/controllers/application.rb里面添加幾行代碼:?

    Ruby代碼??
  • ??around_filter?:record_memory??
  • ??def?record_memory??
  • ????process_status?=?File.open("/proc/#{Process.pid}/status")??
  • ????13.times?{?process_status.gets?}??
  • ????rss_before_action?=?process_status.gets.split[1].to_i??
  • ????process_status.close??
  • ????yield??
  • ????process_status?=?File.open("/proc/#{Process.pid}/status")??
  • ????13.times?{?process_status.gets?}??
  • ????rss_after_action?=?process_status.gets.split[1].to_i??
  • ????process_status.close??
  • ????logger.info("CONSUME?MEMORY:?#{rss_after_action?-?rss_before_action}?\??
  • KB\tNow:?#{rss_after_action}?KB\t#{request.url}")??
  • ??end??


  • 我們定義了一個(gè)AroundFilter,記錄一下處理請(qǐng)求前后的內(nèi)存變化。有了這個(gè)信息,我們接下來(lái)的事情就簡(jiǎn)單了,只需要從production.log里面抽取出來(lái)這行l(wèi)og,進(jìn)行統(tǒng)計(jì)分析就可以了,這也僅僅只需要一行shell就搞定了:?

    Ruby代碼??
  • grep?"CONSUME?MEMORY"?production.log?|?grep?-v?"CONSUME?MEMORY:?0"?|??\??
  • ?grep?-v?"CONSUME?MEMORY:?-"?|??awk?'{print?$3?"\t"?$6?"\t"?$8?}'?|?sort?-r?-n?|?\??
  • ?head?-n?500?>?memory.log???


  • 抽取內(nèi)存記錄,去掉內(nèi)存沒(méi)有增加,去掉內(nèi)存減少(發(fā)生了GC)的請(qǐng)求,然后對(duì)那些處理請(qǐng)求之后內(nèi)存上升的記錄進(jìn)行排序,取出來(lái)前500條記錄保存到memory.log里面,結(jié)果如下所示:?

    Ruby代碼??
  • 增加數(shù)?內(nèi)存占用????請(qǐng)求URL??
  • -----------------------------------------------??
  • 9528??175264??http://www.iteye.com/topic/304594??
  • 9524??129512??http://knityster.iteye.com/blog/172990??
  • 9496??147544??http://www.iteye.com/forums/??
  • 9492??197800??http://duyiwuer.iteye.com/rss??
  • 9452??146668??http://www.iteye.com/forums??
  • 9452??133844??http://wildlife.iteye.com/blog/47693??
  • 9440??157824??http://www.iteye.com/rss/blogs??
  • 9424??204664??http://www.iteye.com/wiki/topic/251964??
  • 9384??142200??http://towerhe.iteye.com/blog/93704??
  • 9380??165372??http://www.iteye.com/wiki/topic/77434??
  • 9368??207460??http://superleo.iteye.com/rss??


  • 第一列是訪問(wèn)了一個(gè)請(qǐng)求以后,Rails進(jìn)程的內(nèi)存上升了9MB多,第二列是處理完請(qǐng)求,Rails進(jìn)程當(dāng)前實(shí)際占了170多MB內(nèi)存,第三列是處理了什么請(qǐng)求。?

    根據(jù)這個(gè)統(tǒng)計(jì)結(jié)果,你可以很容易找出那些造成你Rails進(jìn)程內(nèi)存泄漏的罪魁禍?zhǔn)?#xff0c;哪些請(qǐng)求一訪問(wèn)你的Rails進(jìn)程內(nèi)存就飚升已經(jīng)是一目了然的事情了,這是不是很簡(jiǎn)單?事實(shí)上通過(guò)這個(gè)辦法,JavaEye僅用了半個(gè)多小時(shí),就解決了曾經(jīng)困擾了半年多的內(nèi)存泄漏問(wèn)題,辦法雖土,卻很有效!

    總結(jié)

    以上是生活随笔為你收集整理的监视Rails进程内存泄漏的技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。