[英]Django Celery task on Heroku causes high memory usage
我在Heroku上有一個celery任務,它連接到一個外部API並檢索一些數據,存儲在數據庫中並重復幾百次。 非常快(在~10次循環之后)Heroku開始警告高內存使用率。 有任何想法嗎?
tasks.py
@app.task
def retrieve_details():
for p in PObj.objects.filter(some_condition=True):
p.fetch()
models.py
def fetch(self):
v_data = self.service.getV(**dict(
Number=self.v.number
))
response = self.map_response(v_data)
for key in ["some_key","some_other_key",]:
setattr(self.v, key, response.get(key))
self.v.save()
Heroky記錄
2017-01-01 10:26:25.634
132 <45>1 2017-01-01T10:26:25.457411+00:00 heroku run.5891 - - Error R14 (Memory quota exceeded)
Go to the log: https://api.heroku.com/myapps/xxx@heroku.com/addons/logentries
You are receiving this email because your Logentries alarm "Memory quota exceeded"
has been triggered.
In context:
2017-01-01 10:26:25.568 131 <45>1 2017-01-01T10:26:25.457354+00:00 heroku run.5891 - - Process running mem=595M(116.2%)
2017-01-01 10:26:25.634 132 <45>1 2017-01-01T10:26:25.457411+00:00 heroku run.5891 - - Error R14 (Memory quota exceeded)
你基本上是將一堆數據加載到內存中的Python字典中。 這將導致大量內存開銷,尤其是當您從本地數據庫中獲取大量對象時。
你真的需要將所有這些對象存儲在字典中嗎?
大多數人為這樣的事情做的是:
這樣,您最終只能在任何給定時間將單個對象存儲在內存中,從而大大減少內存占用。
如果我是你,我會尋找將邏輯轉移到數據庫查詢中的方法,或者只是單獨處理每個項目。
為了擴展真正的rdegges想法,以下是我在使用celery / python時幫助減少內存占用的兩個策略:(1)啟動子任務,每個處理只有一個對象和/或(2)使用發電機。
啟動子任務,每個處理只有一個對象:
@app.task def retrieve_details(): qs = PObj.objects.filter(some_condition=True) for p in qs.values_list('id', flat=True): do_fetch.delay(p) @app.task def do_fetch(n_id): p = PObj.objects.get(id=n_id) p.fetch()
現在,您可以調整芹菜,以便在處理N個PObj(任務)后使用--max-tasks-per-child
來保持內存占用率低,從而殺死進程。
使用生成器:您也可以使用生成器嘗試此操作,以便您可以(理論上)在調用fetch后丟棄PObj
def ps_of_interest(chunk=10): n = chunk start = 0 while n == chunk: some_ps = list(PObj.objects.filter(some_condition=True)[start:start + n]) n = len(some_ps) start += chunk for p in some_ps: yield p @app.task def retrieve_details(): for p in ps_of_interest(): p.fetch()
為了我的錢,我會選擇#1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.