繁体   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