簡體   English   中英

如何減少線程python代碼的內存使用?

[英]How to reduce memory usage of threaded python code?

我寫了大約50個類,用於連接和使用機械化和線程的網站。 它們都同時工作,但它們並不相互依賴。 所以這意味着1個類 - 1個網站 - 1個線程。 它不是特別優雅的解決方案,特別是對於管理代碼,因為很多代碼在每個類中重復(但不足以使它成為一個類來傳遞參數,因為一些站點可能需要在方法中間對檢索到的數據進行額外處理 - 像'登錄' - 其他人可能不需要)。 正如我所說,它並不優雅 - 但它有效。 毋庸置疑,我歡迎所有建議如何更好地編寫這個,而不使用每個網站方法的1個類。 添加每個類的附加功能或整體代碼管理是一項艱巨的任務。

但是,我發現,每個線程占用大約8MB內存,因此使用50個正在運行的線程,我們正在考慮大約400MB的使用量。 如果它在我的系統上運行我就不會有問題,但由於它在僅有1GB內存的VPS上運行,因此它開始出現問題。 你能告訴我如何減少內存使用量,還是有其他方法同時使用多個站點?

我使用這個快速測試python程序來測試它是存儲在我的應用程序的變量中的數據是使用內存還是其他東西。 正如您在下面的代碼中看到的,它只處理sleep()函數,但每個線程使用8MB內存。

from thread import start_new_thread
from time import sleep

def sleeper():
    try:
        while 1:
            sleep(10000)
    except:
        if running: raise

def test():
    global running
    n = 0
    running = True
    try:
        while 1:
            start_new_thread(sleeper, ())
            n += 1
            if not (n % 50):
                print n
    except Exception, e:
        running = False
        print 'Exception raised:', e
    print 'Biggest number of threads:', n

if __name__ == '__main__':
    test()

當我運行它時,輸出是:

50
100
150
Exception raised: can't start new thread
Biggest number of threads: 188

通過刪除running = False行,我可以在shell中使用free -m命令測量空閑內存:

             total       used       free     shared    buffers     cached
Mem:          1536       1533          2          0          0          0
-/+ buffers/cache:       1533          2
Swap:            0          0          0

通過將上述測試應用程序運行之前和期間使用的內存差異除以它設法啟動的最大線程數,實際計算為什么我知道它每個線程大約需要8MB。

它可能只分配了內存,因為通過查看top ,python進程僅使用大約0.6%的內存。

使用“每個請求一個線程”對於許多用例來說都很容易。 但是,它需要大量的資源(正如您所經歷的那樣)。

更好的方法是使用異步方法,但不幸的是它要復雜得多。

一些暗示這個方向:

解決方案是替換這樣的代碼:

1)做點什么。
2)等待事情發生。
3)做點別的事。

使用這樣的代碼:

1)做點什么。
2)安排它,以便在發生事情時,完成其他事情。
3)完成。

在其他地方,你有幾個線程可以做到這一點:

1)等待任何事情發生。
2)處理發生的事情。
3)轉到步驟1。

在第一種情況下,如果你正在等待50件事情發生,你就有50個線程在等待50件事情發生。 在第二種情況下,你有一個等待的線程將執行這50個事情中的任何一個。

所以,不要使用線程等待一件事發生。 相反,安排它,以便當事情發生時,其他一些線程將做下一步需要完成的任何事情。

我不是Python的專家,但可能有一些線程池可以控制活動線程的總數,並且一旦完成前一個線程,就會向線程發出“請求”。 請求不必是完整的線程對象,只需要足夠的數據來完成請求。

您也可以構建它,以便您擁有線程池A,其中N個線程ping網站,一旦檢索到數據,將數據交給線程池B,Y線程處理數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM