python性能优化,GIL理解


Cpython和GIL

GIL, Global Interpreter Lock 

  • Cpython解释器的内存管理并不是线程安全的
  • 保护多线程情况下对python对象的访问
  • Cpython解释器使用简单的琐机制避免多个线程同时访问字节码(python是把源文件编译成字节码去执行的)

所以就造成了在一个时刻只有一个线程可以执行字节码,无法利用cpu的多核

GIL的影响

主要就是限制了程序的多核执行

  • 同一个时间只有一个线程执行字节码
  • CPU密集型程序难以利用多核优势
  • IO期间会释放GIL, 对IO密集的程序影响不大(在进行IO操作的时候,GIL被释放,就可以切换不同的线程执行字节码,这也是为什么python可以用来做web开发

如何规避GIL的影响

首先要区分是CPU密集还是IO密集

  • CPU密集型可以使用多进程 + 进程池
  • IO密集可以使用多线程和协程
  • cpython扩展(把python转换成c语言来跑)

为什么有了GIL还要关注线程安全

Python中什么操作才是原子的(一步到位执行完)?

  

  GIL 的作用是:对于一个解释器,只能有一个线程在执行字节码。所以每时每刻只有一条字节码在被执行一个线程。GIL保证了字节码 这层面上是线程安全的。

但是如果你有个操作比如 x += 1,这个操作需要多个字节码操作,在执行这个操作的多条字节码期间的时候可能中途就换线程了,这样就会出现问题。

可以通过 dis 库来查看字节码操作过程。

  • 一个操作如果是一个字节码指令可以完成的,那就是原子的。
  • 原子性可以保证线程安全的

服务端性能优化措施

web应用语言一般不会成为瓶颈

  • 数据结构和算法
  • 数据库层:索引优化,慢查询消除,批量操作减少IO, 引入NoSql提升性能。
  • 网络IO: 批量操作,pipline操作减少IO
  • 使用内存数据库设置缓存: redis/memcached
  • 异步:asyncio,celery
  • 并发:gevent/多线程