python greenlet 背景介绍与实现机制
最近开始研究Python的并行开发技术,包括多线程,多进程,协程等。逐步整理了网上的一些资料,今天整理一下greenlet相关的资料。
并发处理的技术背景
并行化处理目前很受重视, 因为在很多时候,并行计算能大大的提高系统吞吐量,尤其在现在多核多处理器的时代, 所以像lisp这种古老的语言又被人们重新拿了起来, 函数式编程也越来越流行。 介绍一个python的并行处理的一个库: greenlet。 python 有一个非常有名的库叫做 stackless ,用来做并发处理, 主要是弄了个叫做tasklet的微线程的东西, 而greenlet 跟stackless的最大区别是, 他很轻量级?不够, 最大的区别是greenlet需要你自己来处理线程切换, 就是说,你需要自己指定现在执行哪个greenlet再执行哪个greenlet。
greenlet的实现机制
以前使用python开发web程序,一直使用的是fastcgi模式.然后每个进程中启动多个线程来进行请求处理.这里有一个问题就是需要保证每个请求响应时间都要特别短,不然只要多请求几次慢的就会让服务器拒绝服务,因为没有线程能够响应请求了.平时我们的服务上线都会进行性能测试的,所以正常情况没有太大问题.但是不可能所有场景都测试到.一旦出现就会让用户等好久没有响应.部分不可用导致全部不可用.后来转换到了coroutine,python 下的greenlet.所以对它的实现机制做了一个简单的了解.
每个greenlet都只是heap中的一个python object(PyGreenlet).所以对于一个进程你创建百万甚至千万个greenlet都没有问题.
typedef struct _greenlet {
PyObject_HEAD
char* stack_start;
char* stack_stop;
char* stack_copy;
intptr_t stack_saved;
struct _greenlet* stack_prev;
struct _greenlet* parent;
PyObject* run_info;
struct _frame* top_frame;
int recursion_depth;
PyObject* weakreflist;
PyObject* exc_type;
PyObject* exc_value;
PyObject* exc_traceback;
PyObject* dict;
} PyGreenlet;
每一个greenlet其实就是一个函数,以及保存这个函数执行时的上下文.对于函数来说上下文也就是其stack..同一个进程的所有的greenlets共用一个共同的操作系统分配的用户栈.所以同一时刻只能有栈数据不冲突的greenlet使用这个全局的栈.greenlet是通过stack_stop,stack_start来保存其stack的栈底和栈顶的,如果出现将要执行的greenlet的stack_stop和目前栈中的greenlet重叠的情况,就要把这些重叠的greenlet的栈中数据临时保存到heap中.保存的位置通过stack_copy和stack_saved来记录,以便恢复的时候从heap中拷贝回栈中stack_stop和stack_start的位置.不然就会出现其栈数据会被破坏的情况.所以应用程序创建的这些greenlet就是通过不断的拷贝数据到heap中或者从heap中拷贝到栈中来实现并发的.对于io型的应用程序使用coroutine真的非常舒服.
下面是greenlet的一个简单的栈空间模型(from greenlet.c)
下面是一段简单的greenlet代码.
from greenlet import greenlet
def test1():
print 12
gr2.switch()
print 34
def test2():
print 56
gr1.switch()
print 78
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
目前所讨论的协程,一般是编程语言提供支持的。目前我所知提供协程支持的语言包括python,lua,go,erlang, scala和rust。协程不同于线程的地方在于协程不是操作系统进行切换,而是由程序员编码进行切换的,也就是说切换是由程序员控制的,这样就没有了线程所谓的安全问题。
所有的协程都共享整个进程的上下文,这样协程间的交换也非常方便。
相对于第二种方案(I/O多路复用),使得使用协程写的程序将更加的直观,而不是将一个完整的流程拆分成多个管理的事件处理。
协程的缺点可能是无法利用多核优势,不过,这个可以通过协程+进程的方式来解决。
协程可以用来处理并发来提高性能,也可以用来实现状态机来简化编程。我用的更多的是第二个。去年年底接触python,了解到了python的协程概念,后来通过pycon china2011接触到处理yield,greenlet也是一个协程方案,而且在我看来是更可用的一个方案,特别是用来处理状态机。
目前这一块已经基本完成,后面抽时间总结一下。
总结一下:
1)多进程能够利用多核优势,但是进程间通信比较麻烦,另外,进程数目的增加会使性能下降,进程切换的成本较高。程序流程复杂度相对I/O多路复用要低。
2)I/O多路复用是在一个进程内部处理多个逻辑流程,不用进行进程切换,性能较高,另外流程间共享信息简单。但是无法利用多核优势,另外,程序流程被事件处理切割成一个个小块,程序比较复杂,难于理解。
3)线程运行在一个进程内部,由操作系统调度,切换成本较低,另外,他们共享进程的虚拟地址空间,线程间共享信息简单。但是线程安全问题导致线程学习曲线陡峭,而且易出错。
4)协程有编程语言提供,由程序员控制进行切换,所以没有线程安全问题,可以用来处理状态机,并发请求等。但是无法利用多核优势。
上面的四种方案可以配合使用,我比较看好的是进程+协程的模式。
python greenlet 背景介绍与实现机制的更多相关文章
- python greenlet背景介绍与实现机制
并发处理的技术背景 并行化处理目前很受重视, 因为在很多时候,并行计算能大大的提高系统吞吐量,尤其在现在多核多处理器的时代, 所以像lisp这种古老的语言又被人们重新拿了起来, 函数式编程也越来越流行 ...
- Python——greenlet
目录 1. 介绍 2. 父greenlet 3. 实例化 4. 在greenlets间切换 5. 垂死的greenlets 6. greenlet的方法和属性 7. greenlets和Python线 ...
- python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
python与java的内存机制不一样;java的方法会进入方法区直到对象消失 方法才会消失;python的方法是对象每次调用都会创建新的对象 内存地址都不i一样
- Python中的垃圾回收机制
Python的垃圾回收机制 引子: 我们定义变量会申请内存空间来存放变量的值,而内存的容量是有限的,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,而变量名是访问到变量值的唯一方式,所以 ...
- (编程语言+python+变量名+垃圾回收机制)*知识点
编程语言 从低级到高级的发展的过程 1.机器语言 计算机是基于电工作的.(基于高.低电平 1010010101011) 如果用机器语言表现一个字符的意思需要多段代码的行.但是计算机读取的快. 所以机器 ...
- 以python为例讲解闭包机制
以python为例讲解闭包机制 缘起 在学习JS的过程中,总是无可避免的接触到闭包机制,尤其是接触到react后,其函数式的编程思想更是将闭包发扬光大,作为函数式编程的重要语法结构,python自然也 ...
- 第10.4节 Python模块的弱封装机制
一. 引言 Python模块可以为调用者提供模块内成员的访问和调用,但某些情况下, 因为某些成员可能有特殊访问规则等原因,并不适合将模块内所有成员都提供给调用者访问,此时模块可以类似类的封装机制类似的 ...
- Python强大的可变参数传递机制
今天模拟定义map函数.写着写着就发现Python可变长度参数的机制真是灵活而强大. 假设有一个元组t,包含n个成员: t=(arg1,...,argn) 而一个函数f恰好能接受n个参数: f(arg ...
- 【转载】Python中的垃圾回收机制
GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...
随机推荐
- 51nod1289 stack
1289 大鱼吃小鱼 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 收藏 关注 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动 ...
- TWain 在 Qt4 中的调用方法
1.开发环境 Windows7_sp1_x64 Qt4.7.4 + mingw32 twain_32.dll (1.7.1.3) 2.常用缩写 DSM: Data Source Manager 数据源 ...
- 快速切题 sgu136. Erasing Edges
136. Erasing Edges time limit per test: 0.25 sec. memory limit per test: 4096 KB Little Johnny paint ...
- linux中安装tomcat
01.去官网下载指定的安装包http://tomcat.apache.org/download-70.cgi 链接地址 02.在software目录下 使用命令wget 刚才复制的地址即可 03.使用 ...
- windows下查看端口是否被占,以及端口被哪个程序占用
如何查看端口被是否被占用 在 “ 命令提示符 ” 中输入 “netstat -an”, 即可显示本机所有开放端口.下表是具体的说明. 数据列 说明 propo 指连接使用的协议名称 local add ...
- 怎样配置visio的数据库驱动程序
怎样配置visio的数据库驱动程序 百度师傅最快的到家服务,最优质的电脑清灰 在使用visio进行反向工程画数据库模型图时,需要进行数据库驱动程序的配置.下面以visio2003给大家演示怎样配置 ...
- redis安装全过程
1. 从官网上下载redis. 2.安装gcc 3.进入./redis/src目录下make MALLOC =libc 4.遇到的问题 Redis简介: Redis是一个开源的使用ANSI C语言编写 ...
- Linux系统下 MYSQL数据库中的数据库文件在本机内迁移 (需暂停服务的方式)
Linux系统下 MYSQL数据库中的数据库文件在本机内迁移 本机采用Ubuntu16.04系统,tar方式安装MySQL5.7.21 数据库安装文件夹为 /home/devil/mysql 现 ...
- koa/koa2项目搭建
一键生成koa/koa2项目: 1. npm install -g koa-generator 2.新建项目目录 koa mytest (koa1项目) koa2 koa2test (koa2项目) ...
- windows php下memcache+memcached安装与配置
环境声明: 服务器:Windows7 64-bit:Memcached:Memcached 64-bit for Windows(64位) 安装过程 解压刚刚下载的压缩包,得到两个文件:memcach ...