Gevent

特点:
	是一个基于libev的并发库 它为各种并发和网络相关的任务提供了整洁的API
	基于libev的高效时间循环
	基于greenlet的轻量级执行单元
	重用Python标准库API内容(比如Event Queues)
	socket谢童ssl
	利用线程池或者c-cares来执行DNS查询

a. 进程 线程 协程

进程:
    概念: 进程是正在运行程序的实例
    特点: 具有独立地址空间 是操作系统资源分配的基本单元
    进程上下文: 进程的物理实体与支持进程运行的物理环境,包括:地址空间 系统栈 打开文件表 。。。
    上下文切换: 由一个进程的上下文转到另一个进程的上下文
    系统开销: 运行操作系统程序完成系统管理工作所话费的时间和空间
    一个进程可以包括多个线程

线程:
	- 线程是程序执行的最小单位
	- 多线程的优点: 提高程序的并发性
协程:
	- 协程可以认为是一种用户态的线程,与系统提供的线程不同点是 他需要主动让出cpu时间,而不是由系统进行调度,即控制权在程序员手上。

优缺点:
	- 进程创建销毁成本高
	- 线程开销比进程低,但切换成本高,线程间同步变复杂。
	- 协程不陷入内核的情况进行上下文切换,没有同步问题,但需要手动切换。

下图解释:
    进程是有状态的 刚启动时就绪态,如果进程调度算法调度到这个进程 就会变成执行态。
    分配的算法是有时间片的 当时间片使用完 会继续切回就绪态
    如果时间片没有使用完 当有IO发生就会阻塞态 阻塞完成 继续切回用户态

Gevent

 

b. 阻塞 非阻塞 同步 异步

阻塞与非阻塞:
     
    网络IO
        - 对于网络IO主要指socket,socket是进程间通信的一种方法 对于阻塞与非阻塞的情况就是在使用socket中在调用它的API时它的connect read write 会发生阻塞,也可以设置为非阻塞。
        - socket会在connect/read/write时发生阻塞
    阻塞
        - 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回
    非阻塞
        - 非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回


同步与异步:

	同步:
		同步就是发生调用时,一定等待结果返回,整个调用才结束。

	异步:
		异步就是发生调用后,立即返回,不等待结果返回,被调用者通过状态/通知来通知调用者,或通过回调函数处理这个调用。


	同步异步 与 阻塞非阻塞区别:
		阻塞/非阻塞 它们是程序在等待消息(无所谓同步或者异步)时的状态。
		同步/异步 是程序获得关注消息通知的机制。

		同步阻塞: 效率最低(日志程序)
		同步非阻塞: 效率也不高(需要轮询)
		异步阻塞: 一般模式线程回调
		异步非阻塞: IOCP

 

connect 阻塞做的操作
	客户端和服务端做交互的时候,客户端连接服务器,connect时候阻塞会自动打开,会向服务端发送一个序列号,服务端接受后处于阻塞。

Gevent

数据接受阻塞
	应用层recvfrom调用过程中会发生一个系统调用。系统调用会陷入内核里面。如果没有数据准备好,会等待数据直到数据准备好,内核得到数据把数据复制到用户空间,在返回。

Gevent

c. 并发 并行

#并发
	并发是指两个或多个事件在同一时间间隔发生。就是同时处理很多事情,比如串行同时处理一件事情。
	在单核系统中,为了提高cpu利用率,系统采用时间片轮询等调度方式,对多个线程轮换执行,在宏观上看线程是同时执行的 从微观上看某一时刻只执行一个线程。在发生资源竞争或者大量的上下文切换会导致性能消耗。

d. monkey patch

# monkey patch

	- 在动态语言中,不去改变源码而对功能进行追加和变更就叫做 Monkey Patching(猴子补丁)
	1. 追加功能
	2. 功能变更
	3. 修正程序错误
	4. 增加钩子,在执行某个方向的同时执行一些其他的处理 如打印日志 实现AOP等

	#模块
		- socket
		- dns
		- time
		- select
		- thread
		- os
		- ssl
		- subprocess
		- sys
		- builtins
		- signal
	默认阻塞的模块都被替换成非阻塞,协作式的。
	gevent支持异步协作的域名解析系统。
	time.sleep只是协作内休眠,并不阻塞线程。
import gevent
from gevent import monkey

urls = ["http://www.baidu.com","http://www.zhihu.com","http://www.xiaohuar.com/"]
import urllib2
import timeit
def print_head(url):
    print("start %s"%url)
    gevent.sleep(0)
    data = urllib2.urlopen(url).read()
    print("%s:%s bytes: %r" %(url,len(data),data[:50]))


def test():
    jobs = [gevent.spawn(print_head,url) for url in urls]
    gevent.joinall(jobs)

monkey.patch_all()      #加上这行效率明显提升

print timeit.Timer(stmt='test()',setup="from __main__ import test").timeit(number=10)
实例演示

相关文章: