性能优化

上下文切换

当一个程序进入 I/O 等待时,暂停执行,这样内核就能执行 I/O 请求相关的低级操作,直到 I/O 操作完成时才继续

上下文切换是相当重 量级的操作。它要求我们保存程序的状态(丢失了我们在 CPU 层面上任何类型的 缓存),放弃使用 CPU。之后,当我们允许再次运行时,我们必须花时间在主板上 重新初始化程序并准备好继续运行

事件循环

回调 or future Future 由 gevent.spawn 来创建,使用了一个函数和传递给这个函数的参数,并 且启动了一个负责运行这个函数的 greenlet。greenlet 能够被看作一个 future, 因为你声明的函数一旦运行完成,它的值就会包含在 greenlet 的 value 域中


multiprocessing

  • 把你的工作拆分成独立的工作单元。
  • 如果你的工作者所花的时间是可变的,那就考虑随机化工作序列(另一个例子 就是处理大小可变的文件)。
  • 对你的工作队列进行排序,这样首先处理最慢的任务可能是一个平均来说有用 的策略。
  • 使用默认的 chunksize,除非你已经验证了调节它的理由。
  • 让任务数量与物理 CPU 数量保持一致(默认的 chunksize 再次为你考虑到 了,尽管它默认会使用超线程,这样可能不会提供额外的性能收益)。

Queue 主要看通信

序列化(pickle)和同步,使用 Queue 具有相当的开销

使用一个更少的 Queue 的单进程解决方案明显要比使用两个 或多个进程的要快 两个进程完成这个例子要比一个进程稍快一点,而四个或八个进程则比一个进程要更慢


进程通信 multiprocessing.Value mmap


内存

基础类型的对象开销高 整数对象已经存在缓存中,这样就可以被复用。 Python 缓存了类似整数的基础对象为以后所用。在一个RAM有限的系统中,这会造成问题,所以你应该注意到这些基础类型可能会构建在缓存中。

Array 创建了一个连续的RAM块来保存底层数据,高效地存储了类似于整数、浮点数和字符的基础类型,但没有复数或者类 注意在 array 中的唯一数字不是 Python 对象,它们在 array 中是字节。如果我 们要解引用它们中任何一个,那么一个新的 Python int 对象将会被构建。如果你想要在它们之上来做计算,不会发生整体上的节省,但是如果你想要把数组传递给一 个外部进程或者只使用一些数据,你应该看到相比使用一个整数的 list 来说,大大节约了 RAM