解释器将代码编译成字节码执行。
使用__code__.co_code查看字节码;函数名不加括号在前
将字节码以人类可读的方式输出
导入dis模块,使用dis.dis(函数名)查看
可以简单的产看解释器的执行过程
输出分为5列,分别代表:字节码对应在源码中的行号,字节码在字节码串中的第几个字节,字节码人类可读的命名,字节码参数,字节码参数的内容
帧是包含一端代码运行时所需的信息和环境,当调用一次函数时,就是进栈,函数结束时,栈被弹出,使用return value弹入下一个栈。每一帧对应一个函数的调用。一个函数可能有多个帧,比如递归(函数调用本身)
python解释器包含常用的三种栈,调用栈,数据栈,块栈。
调用栈:执行字节码时操作
数据栈:执行函数时操作
快栈:执行特定的控制流(循环、判断)
是让解释器在同一时刻仅有一个线程可被调度执行。对单核高效简单。
多核的话可以采用进程加协程来发挥多核环境计算能力
对于I-O密集型任务,线程会在发生阻塞时主动释放GIL,以便其他线程执行。
对于计算密集型任务,采取超时策略:
超时后,依然无法获取锁,则发出请求。对正在执行的线程在解释循环内会检查该标记,然后释放锁,切换其他线程执行,其自身进入等待状态(典型的协作机制)
CPython使用系统线程,且没有实现线程调度。所以,具体等待哪个线程被切换执行,有操作系统决定,甚至发出请求和被切换执行的也未必是用一线程。
每个对象头部都有一个引用计数器。引用该对象时,计数增加,反之减少。当技术归0时,立即调用回收函数清理并释放内存。
但引用计数一旦出错或忘记调用,要么计数无法归零导致内存泄漏,要么忘记增加计数让对象提前回收。
他还会引起内存管理问题,对象在传递过程中,即便内容未被修改,可引用计数依然让其内存发生了变动。这可能会导致CPU缓存错失率提升,甚至让写时复制(Copy-On-Write)机制失效。
为实现循环引用垃圾回收,所有可能导致问题的容器类型,都必须使用专门的内存分配函数。