Python 线程池/进程池 内存管理

原创 2018年04月16日 15:00:56

concurrent.futures 线程池/进程池内存管理

起因

之前进行爬虫任务的时候遇到了这么一个需求,1G 内存的机器跑爬虫,爬取一个网站的数据,之前使用的是这样一种方式:

 futures = list()
 with ThreadPool(max_workers=20) as exc:
      for tr in table.select("tr"):

          # 取线程执行结果
          future = exc.submit(self.get_asn, tr.strings)
          futures.append(future)

# 使用 as_completed 异步方式处理完成任务的线程
for future in as_completed(futures):
    result = future.result()
    # 拼接 asn.json 的 path
    file_path = result["asn"] + ".json"
    asn_file = os.path.join(self.base_data_path, file_path)

    with open(asn_file, "w", encoding="utf8") as f:
        f.write(json.dumps(result))

使用了 concurrent.futures 的 ThreadPoolExecutor submit 方法,因为开启了20个线程同时爬取,连接网站的速度还很快,任务很快就被处理完成了,可以看到我时完成一个任务的时候就进行写文件了操作,但是2分钟后很快程序就终止了,监控程序发现时由于程序内存占用达到 80% 被系统 Kill 掉了。

  • 为什么内存会爆呢?监控内存显示,程序处理完任务之后,内存并没有被立刻释放,而是有很长时间延迟之后才被释放( 在此吐槽 python GC)

改进方法:

参考 https://stackoverflow.com/questions/34770169/using-concurrent-futures-without-running-out-of-ram

# 允许同时进行的工作数
MAX_JOBS_IN_QUEUE = 1000


tr_list = table.select("tr")
tr_left = len(tr_list) - 1  # <----
tr_iter = iter(tr_list)  # <------
jobs = dict()

  with ThreadPool(max_workers=20) as exc:
      while tr_left:
          print("#" * 100, "TASK: {} <===>  JOB: {}".format(tr_left, len(jobs)))
          for tr in tr_iter:
              # 取线程执行结果
              job = exc.submit(self.get_asn, tr.strings)
              jobs[job] = tr
              if len(jobs) > MAX_JOBS_IN_QUEUE:
                  break  # limit the job submission for now job

          # 使用 as_completed 异步方式处理任务线程
          for job in as_completed(jobs):
              tr_left -= 1  # one down - many to go...   <---
              result = job.result()
              # 从字典中删除结果,因为我们不需要存储它
              del jobs[job]

              # 拼接 asn.json 的 path
              file_path = result["asn"] + ".json"
              asn_file = os.path.join(self.base_data_path, file_path)

              with open(asn_file, "w", encoding="utf8") as f:
                  f.write(json.dumps(result))
              break

改进后内存在切换 html 爬取的时候,会偶尔会升高一下,最高 65%,平均在 35% 左右。

  • ProcessPoolExecutor 进程同理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SmallTankPy/article/details/79960739

Python 进程池中嵌套使用线程池

在日志分析脚本中,利用多进程并行处理同一server上的多个日志文件但是一个子进程处理一份日志文件过程中,亦有大量循环处理(串行)的情况,所以考虑若在该子进程中将一些任务改为多线程,应该可以获得较明显...
  • kai404
  • kai404
  • 2017-04-27 15:53:22
  • 1256

Python 多进程_进程池_多线程_线程池实现比较

多进程: #!/usr/bin/env python #coding:gbk #=========================================================...
  • zhou191954
  • zhou191954
  • 2012-12-12 14:05:11
  • 686

内存池、进程池、线程池介绍及线程池C++实现

内存池 平常我们使用new、malloc在堆区申请一块内存,但由于每次申请的内存大小不一样就会产生很多内存碎片,造成不好管理与浪费的情况。 内存池则是在真正使用内存之前,先申请分配一定数量的、大小...
  • ywcpig
  • ywcpig
  • 2016-09-16 20:36:33
  • 2370

内存池、进程池、线程池

由于服务器的硬件资源“充裕”,那么提高服务器性能的一个很直接的方法就是以空间换时间,即“浪费”服务器的硬件资源,以换取其运行效率。这就是池的概念。...
  • u011012049
  • u011012049
  • 2015-09-14 10:54:16
  • 4594

Linux进程池与线程池以及线程池的简单实现

进程池是由服务器预先创建的一组子进程,这些子进程的数目在3-10个之间。httpd守护进程就是使用了包含7个子进程的进程池来实现并发的。线程池中的线程数量应该和CPU数量差不多进程池中的所有子进程都运...
  • jyy305
  • jyy305
  • 2017-06-04 13:38:04
  • 390

多线程、多进程、线程池、进程池

多任务不管是单核CPU还是多核CPU,一旦任务数量超过核数,OS都会把每个任务轮流调度到每个核心上。OS实现多进程和多线程往往是通过时间片的形式执行的,即让每个任务(进程/线程)轮流交替执行,因为时间...
  • acelit
  • acelit
  • 2017-04-11 15:01:18
  • 1023

Linux高性能服务器编程——进程池和线程池

进程池和线程池 池的概念 由于服务器的硬件资源“充裕”,那么提高服务器性能的一个很直接的方法就是以空间换时间,即“浪费”服务器的硬件资源,以换取其运行效率。这就是池的概念。池是一组...
  • walkerkalr
  • walkerkalr
  • 2014-07-12 21:54:05
  • 5725

线程池代替进程池

一.问题引入 刚进入一家新公司,在公司的一些培训中得知,我们的服务端系统中,底层库的任务调度用的是进程池的实现,也就是创建许多子进程来进行执行业务处理,进程池技术是比较早的一种技术了,在现在众多高性...
  • Doctorllm
  • Doctorllm
  • 2015-03-27 11:08:19
  • 802

Linux--线程池与进程池及线程池的简单实现

池由于服务器的硬件资源“充裕”,那么提高服务器性能的一个很直接的方法就是以空间换时间,即“浪费”服务器的硬件资源,以换取其运行效率。这就是池的概念。池是一组资源的集合,这组资源在服务器启动之初就被创建...
  • sayhello_world
  • sayhello_world
  • 2017-06-01 17:16:29
  • 2890

python---进程与线程(四)---process类,进程间通信,进程池,协程

Process([group [, target [, name [, args [, kwargs]]]]])   group: 线程组,目前还没有实现,库引用中提示必须是None;    targ...
  • defending
  • defending
  • 2017-07-20 15:45:49
  • 459
收藏助手
不良信息举报
您举报文章:Python 线程池/进程池 内存管理
举报原因:
原因补充:

(最多只允许输入30个字)