【python】threadpool的内存占用问题

摘要:
因为线程池会导致严重的内存使用问题!当使用线程池时,内存不会在每个线程退出后释放,而是一直累积。在实际使用中,我从Mongo获得了大量数据。线程池在处理过程中占用的内存高达50g,而线程占用的内存稳定在1g

先说结论:

在使用多线程时,不要使用threadpool,应该使用threading, 尤其是数据量大的情况。因为threadpool会导致严重的内存占用问题!

对比threading和threadpool的内存占用

# coding=utf-8

import time
import os
import psutil
import json
import threadpool
import threading


class TEST(object):
    # 获取数据,使用yield, 每次返回一个len=10的list, list中的每一项是一个线程的数据
    def get_data(self):
        multi_list = list()
        for i in range(100):
            data = "abcdefg" * 100000
            multi_list.append(data)
            if len(multi_list) % 10 == 0:
                yield multi_list
                multi_list = list()

    # 测试函数
    def test(self):
        for data in self.get_data():
            mem = psutil.Process(os.getpid()).memory_info().rss
            print "[test] mem %s" % mem    # 打印内存占用情况
            self.deal_threadpool(data)      # 使用threadpool
            # self.deal_multi_thread(data)  # 使用threading

    # 待对比方法,threadpool
    def deal_threadpool(self, data_list):
        pool = threadpool.ThreadPool(10)
        requests = threadpool.makeRequests(self.sub_task, data_list)
        [pool.putRequest(req) for req in requests]
        pool.wait()

    # 待对比方法,threading
    def deal_multi_thread(self, data_list):
        threads = list()
        for data in data_list:
            threads.append(threading.Thread(target=self.sub_task, args=(data,)))
        for t in threads:
            t.start()
        for t in threads:
            t.join()

    def sub_task(self, data):
        return


if __name__ == "__main__":
    mem = psutil.Process(os.getpid()).memory_info().rss
    print "[main] mem %s" % mem
    obj = TEST()
    obj.test()
    mem = psutil.Process(os.getpid()).memory_info().rss
    print "[main] mem %s" % mem

结果:

1. 使用threadpool时

[main] mem 9760768
[test] mem 16764928
[test] mem 23924736
[test] mem 26820608
[test] mem 29720576
[test] mem 31911936
[test] mem 34795520
[test] mem 36978688
[test] mem 39161856
[test] mem 41340928
[test] mem 43524096
[main] mem 43606016

2. 使用threading时

[main] mem 9760768
[test] mem 16764928
[test] mem 23838720
[test] mem 16969728
[test] mem 23838720
[test] mem 16969728
[test] mem 23838720
[test] mem 16973824
[test] mem 23842816
[test] mem 16973824
[test] mem 23842816
[main] mem 16973824

对比可以看出,

使用threading时,每次线程退出可以正确的释放内存,内存占用的最大值很稳定。

使用threadpool时,每次线程退出后内存都没有释放,而是一直累加。在我实际使用的过程中,从mongo获取了大量的数据,threadpool在处理过程中占用的内存高达50g,而使用threading后内存占用稳定在了1g.

免责声明:文章转载自《【python】threadpool的内存占用问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python学习(一) —— matplotlib绘制三维轨迹图认识WPF下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

屌炸天,Oracle 发布了一个全栈虚拟机 GraalVM,支持 Python!

前阵子,Oracle 发布了一个黑科技 “GraalVM”,号称是一个全新的通用全栈虚拟机,并具有高性能、跨语言交互等逆天特性,真有这么神奇? GraalVM 简介 GraalVM 是一个跨语言的通用虚拟机,不仅支持了 Java、Scala、Groovy、Kotlin 等基于 JVM 的语言,以及 C、C++ 等基于 LLVM 的语言,还支持其他像 Jav...

Android多开/分身检测

原文:https://blog.darkness463.top/2018/05/04/Android-Virtual-Check/ 多开/分身原本用于方便有多个微信/QQ解决同时登录的问题,但近来年被各种黑产所利用,多见于薅羊毛,部分多开App甚至提供了篡改功能。对于普通用户根本不会有多开的需求的App,一旦检测到当前运行在多开环境下,有理由限制该用户的后...

钉钉小程序中使用F2图表绘制条形图

预览: 要求: 横向柱状图(条形图); 数据最大的柱状图用橙色(#ff6600),数据最小的柱状图用绿色(#33CC00),中间的数据的柱状图用蓝色(#1890ff); 柱状图颜色渐变,左浅右深; y轴的当前月份加粗,字号加大,不足10月的在月份前加0; 柱状图顶部显示数据大小; 图例显示最大数据和最低数据的颜色。 npm下载F2图表: npm in...

存储过程中SELECT INTO的使用

在MySQL存储过程中使用SELECT …INTO语句为变量赋值:   用来将查询返回的一行的各个列值保存到局部变量中。 要求:   查询的结果集中只能有1行。 SELECT col_name[,...] INTO var_name[,...] table_expr 使用SELECT …INTO语句在数据库中进行查询,并将得到的结果赋值给变量。   ①co...

3、Python字符编码区分utf-8和utf-8-sig

Python 读取文件首行多了"ufeff"字符串 python读取B.txt文件时,控制台打印首行正常,但是若是用首行内容打开文本的话,就会报错: Traceback (most recent call last): A File "E:/python project/multiProcess/test.py", line 32, in <mo...

手把手教你emacs cedet C/C++自动补全

  CEDET是emacs非常强大的一个扩展,已经被包含在gnu emacs中,代码补全是个很方便的功能,已经有很多文章介绍过这方面的了,其中算最全面的是 A Gentle introduction to Cedet 用CEDET浏览和编辑C++代码 用CEDET浏览和编辑C++代码(续) – 使用Emacs 23.2内置的CEDET 这三篇文章已经详...