异步IO/数据库/队列/缓存
同步与异步的性能区别
mport gevent def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(0.5)
print('Task %s done' % pid) def synchronous():
for i in range(1,10):
task(i) def asynchronous():
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads) print('Synchronous:')
synchronous() print('Asynchronous:')
asynchronous() '''
Synchronous #(这里串行,一个一个执行,每执行一个睡眠0.5s)
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
Asynchronous #(异步执行,这时=0.5s全部打印出来)
Task 0 done
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
'''
上面程序的重要部分是将task函数封装到Greenlet内部线程的gevent.spawn
。 初始化的greenlet列表存放在数组threads
中,此数组被传给gevent.joinall
函数,后者阻塞当前流程,并执行所有给定的greenlet。执行流程只会在 所有greenlet执行完后才会继续向下走。
遇到IO阻塞时会自动切换任务
from gevent import monkey; monkey.patch_all()
import gevent
from urllib.request import urlopen def f(url):
print('GET: %s' % url)
resp = urlopen(url)
data = resp.read()
print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://github.com/'),
])
通过gevent实现单线程下的多socket并发
server:
import sys
import socket
import time
import gevent from gevent import socket,monkey
monkey.patch_all()
def server(port):
s = socket.socket()
s.bind(('0.0.0.0', port))
s.listen(500)
while True:
cli, addr = s.accept()
gevent.spawn(handle_request, cli)
def handle_request(s):
try:
while True:
data = s.recv(1024)
print("recv:", data)
s.send(data)
if not data:
s.shutdown(socket.SHUT_WR) except Exception as ex:
print(ex)
finally: s.close()
if __name__ == '__main__':
server(8001)
client:
#!/usr/bin/env python
# -*- coding:utf-8 -*- import socket, threading HOST = 'localhost' # The remote host
PORT = 8001 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
# while True:
# msg = bytes(input(">>:"),encoding="utf-8")
# s.sendall(msg)
# data = s.recv(1024)
# data = data.decode()
# #print(data)
#
# print('Received:', repr(data))
# s.close() def foo(num):
msg = bytes('hello girl',encoding="utf-8")
s.sendall(msg)
data = s.recv(1024)
data = data.decode()
print('Received[%s]:%s' %(num, repr(data)) ) if __name__ == '__main__':
res_lsit = []
for i in range(20000):
t = threading.Thread(target=foo,args=(i,))
t.start()
res_lsit.append(t) for r in res_lsit:
r.join() s.close()
论事件驱动与异步IO
事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。
让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型。下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。
在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。
在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。
在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。
当我们面对如下的环境时,事件驱动模型通常是一个好的选择:
- 程序中有许多任务,而且…
- 任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
- 在等待事件到来时,某些任务会阻塞。
当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。
网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。
Select\Poll\Epoll异步IO
http://www.cnblogs.com/linkenpark/p/5305486.html
selectors模块
This module allows high-level and efficient I/O multiplexing, built upon the select
module primitives. Users are encouraged to use this module instead, unless they want precise control over the OS-level primitives used.
#!/usr/bin/env python
# -*- conding:utf-8 -*- import selectors
import socket sel = selectors.DefaultSelector() def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read) def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close() sock = socket.socket()
sock.bind(('localhost', 10000))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept) while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
异步IO/数据库/队列/缓存的更多相关文章
- Python之路,Day10 - 异步IO\数据库\队列\缓存
Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...
- Python之路第一课Day10--随堂笔记(异步IO\数据库\队列\缓存)
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...
- Python 第七篇:异步IO\数据库\队列\缓存
Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SSH Tws ...
- 异步IO\数据库\队列\缓存\RabbitMQ队列
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...
- Day9 - 异步IO\数据库\队列\缓存
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...
- Python - 异步IO\数据库\队列\缓存
协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,协程一定是在单线程运行的. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和 ...
- Python之路第一课Day11--随堂笔记(异步IO\数据库\队列\缓存之二)
一.RabbitMQ队列 1.安装: a.官网: 安装 http://www.rabbitmq.com/install-standalone-mac.html b.安装python rabbitMQ ...
- Python之路,Day9 - 异步IO\数据库\队列\缓存
https://www.cnblogs.com/alex3714/articles/5248247.html http://www.cnblogs.com/wupeiqi/articles/51327 ...
- day10--异步IO\数据库\队列\缓存
上节回顾: 线程 vs 进程 https://www.cnblogs.com/alex3714/articles/5230609.html https://www.cnblogs.com/alex ...
随机推荐
- SharePoint 2013 开发——SharePoint APP介绍
博客地址:http://blog.csdn.net/FoxDave 新的APP模型让我们能够创建看起来像是SharePoint的一部分的应用程序,但是它完全运行在独立于SharePoint服务器 ...
- Windows Server 2012 R2 设置
一.任务栏左下角启动服务器管理器,然后进行设置.1.登录不显示服务器管理器 2.本地服务器,看到右边的IE增强的安全配置,如图所示,关闭两项内容.这样就关闭了IE增强安全提示框. 3.“工具”菜单,启 ...
- javascript面向对象知识点
首先,声明何为对象:对象是键值对的集合 其次,声明:变量就是键值对 再次,声明:函数也是变量 1. JavaScript包含:ECMAScript(核心).DOM(文档对象模型)和BOM(浏览器对象模 ...
- ThinkPHP查询数据与CURD
一.创建连接 在配置文件中使用如下配置: /* 数据库设置 */ 'DB_TYPE' => 'mysql', // 数据库类型 'DB_HOST' => 'localhost', // 服 ...
- VS2013失去智能提示如何恢复
一般智能提示包括,输入智能提示,鼠标移到类,方法,接口,变量上面自动提示相关信息,VS2013常常会失去这种提示功能,遇到这种情况可以这样解决: 1.在开发环境中随便打开一个xxx.aspx页面,也就 ...
- IOS 作业项目(4)步步完成 画图 程序(剧终)
// // CHViewController.m // SuperDrawingSample // // Created by JaikenLI on 13-11-21. // Copyrig ...
- parse,tryparse区别
Convert.ToInt32.int.Parse(Int32.Parse).int.TryParse.(int) 四者都可以解释为将类型转换为 int,那它们的区别是什么呢? Convert.ToI ...
- [转]SQLite C/C++
SQLite C/C++ http://blog.csdn.net/diaoser/article/details/6830786 辅助工具工具 Sqlite数据库的管理工具有SQLiteMana ...
- magento在产品详细页面添加分享链接的方法
1,在产品详细页面的对用位置加入一下代码 <div class="sharethis_box"> <?php echo $this->ge ...
- Android Listener 监听的几种写法
Android中,View的Listener方法,在是否使用匿名类匿名对象时,有各种不同的写法. OnClickListener和其他Listener方法一样,都是View类的接口,重载实现后就能使用 ...