python多进程中的内存复制(实例讲解)


Posted in Python onJanuary 05, 2018

比较好奇python对于多进程中copy on write机制的实际使用情况。目前从实验结果来看,python 使用multiprocessing来创建多进程时,无论数据是否不会被更改,子进程都会复制父进程的状态(内存空间数据等)。所以如果主进程耗的资源较多时,不小心就会造成不必要的大量的内存复制,从而可能导致内存爆满的情况。

示例

举个例子,假设主进程读取了一个大文件对象的所有行,然后通过multiprocessing创建工作进程,并循环地将每一行数据交给工作进程来处理:

def parse_lines(args):
 #working
 ...
def main_logic():
 f = open(filename , 'r')
 lines = f.readlines()
 f.close()
 pool = multiprocessing.Pool(processes==4)
 rel = pool.map(parse_lines , itertools.izip(lines , itertools.repeat(second_args)) , int(len(lines)/4))
 pool.close()
 pool.join()

以下是top及ps结果:

python多进程中的内存复制(实例讲解)

(四个子进程)

python多进程中的内存复制(实例讲解)

(父进程及四个子进程)

由上两张图可以看出父进程及子进程都各自占用了1.4G左右的内存空间。而大部分内存空间存储的是读数据lines,所以这样的内存开销太浪费。

优化计划

1: 在主进程初期未导入大量的py库之前创建进程,或者动态加载py库。

2:通过内存共享来减少内存的开销。

3: 主进程不再读取文件对象,交给每个工作进程去读取文件中的相应部分。

改进代码:

def line_count(file_name):
 count = -1 #让空文件的行号显示0
 for count,line in enumerate(open(file_name)): pass
 #enumerate格式化成了元组,count就是行号,因为从0开始要+1
 return count+1
def parse_lines(args):
 f = open(args[0] , 'r')
 lines = f.readlines()[args[1]:args[2]] #read some lines
 f.close() 
 #working
def main_logic(filename,process_num):
 line_count = line_count(filename)
 avg_len = int(line_count/process_num)
 left_cnt = line_count%process_num;
 pool = multiprocessing.Pool(processes=process_num)
 for i in xrange(0,process_num):
  ext_cnt = (i>=process_num-1 and [left_cnt] or [0])[0]
  st_line = i*avg_len
  pool.apply_async(parse_lines, ((filename, st_line, st_line+avg_len+ext_cnt),)) #指定进程读某几行数据
 pool.close()
 pool.join()

再次用top或者ps来查看进程的内存使用情况:

python多进程中的内存复制(实例讲解)

(四个子进程)

python多进程中的内存复制(实例讲解)

(父进程及四个子进程)

小结

对比两次的内存使用情况,改进代码后父进程及子进程所占用的内存明显减少;所有内存占用相当于原来的一半,这就是减少内存复制的效果。

关于内存使用这方面还有不少优化方法和空间,稍后继续研究。

以上这篇python多进程中的内存复制(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python文件读写并使用mysql批量插入示例分享(python操作mysql)
Feb 17 Python
Python中类的定义、继承及使用对象实例详解
Apr 30 Python
详解Python3中的Sequence type的使用
Aug 01 Python
Python构建XML树结构的方法示例
Jun 30 Python
python实现监控某个服务 服务崩溃即发送邮件报告
Jun 21 Python
Flask框架web开发之零基础入门
Dec 10 Python
对python实现合并两个排序链表的方法详解
Jan 23 Python
OpenCV Python实现拼图小游戏
Mar 23 Python
python实现文字版扫雷
Apr 24 Python
Python执行时间的几种计算方法
Jul 31 Python
python递归函数用法详解
Oct 26 Python
python爬虫scrapy基本使用超详细教程
Feb 20 Python
使用python和Django完成博客数据库的迁移方法
Jan 05 #Python
Python3多线程爬虫实例讲解代码
Jan 05 #Python
python编写微信远程控制电脑的程序
Jan 05 #Python
使用python爬虫实现网络股票信息爬取的demo
Jan 05 #Python
简单实现python收发邮件功能
Jan 05 #Python
5款非常棒的Python工具
Jan 05 #Python
Python基于列表模拟堆栈和队列功能示例
Jan 05 #Python
You might like
php判断输入不超过mysql的varchar字段的长度范围
2011/06/24 PHP
浅析PHP原理之变量分离/引用(Variables Separation)
2013/08/09 PHP
PHP实现的折半查找算法示例
2017/12/19 PHP
基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
2019/05/25 PHP
ExtJS 2.0实用简明教程 之ExtJS版的Hello
2009/04/29 Javascript
JS面向对象、prototype、call()、apply()
2009/05/14 Javascript
Jquery数独游戏解析(一)-页面布局
2010/11/05 Javascript
js call方法详细介绍(js 的继承)
2013/11/18 Javascript
iframe里的页面禁止右键事件的方法
2014/06/10 Javascript
NodeJS学习笔记之(Url,QueryString,Path)模块
2015/01/13 NodeJs
原生js获取元素样式的简单方法
2016/08/06 Javascript
Angular2学习笔记——详解NgModule模块
2016/12/02 Javascript
js实现炫酷的左右轮播图
2017/01/18 Javascript
node.js基于mongodb的搜索分页示例
2017/01/22 Javascript
详解Vue CLI 3.0脚手架如何mock数据
2018/11/23 Javascript
在vue+element ui框架里实现lodash的debounce防抖
2019/11/13 Javascript
js实现左右轮播图
2020/01/09 Javascript
BootStrap前端框架使用方法详解
2020/02/26 Javascript
JavaScript常用工具函数大全
2020/05/06 Javascript
Vue封装全局过滤器Filters的步骤
2020/09/16 Javascript
python实现合并两个数组的方法
2015/05/16 Python
以一个投票程序的实例来讲解Python的Django框架使用
2016/02/18 Python
python中判断文件编码的chardet(实例讲解)
2017/12/21 Python
详解Python3中的迭代器和生成器及其区别
2018/10/09 Python
Python如何实现转换URL详解
2019/07/02 Python
使用pyecharts生成Echarts网页的实例
2019/08/12 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
羽毛球社团活动总结
2014/06/27 职场文书
反对四风问题自我剖析材料
2014/09/29 职场文书
毕业生代领毕业材料的授权委托书
2014/09/29 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
2015年仓库管理工作总结
2015/05/25 职场文书
ThinkPHP5和ThinkPHP6的区别
2021/03/31 PHP
css3实现的加载动画效果
2021/04/07 HTML / CSS
python 模块重载的五种方法
2021/04/24 Python
浅谈如何保证Mysql主从一致
2022/03/13 MySQL