动态类型是如何一步步拖慢你的python程序的
杂谈
人人都知道python慢,这都变成了人尽皆知的事情了,但你知道具体是什么拖慢了python的运行吗?
动态类型肯定要算一个!
动态类型,能够提高开发效率,能够让我们更加专注逻辑开发,使得编程更加灵活。
a = 1
a = 'a'
a = 2.3
你完全不需要定义变量的类型,尽管写代码即可,解释器将动态判断变量的类型。
当然,有了动态类型,肯定有一种静态类型与之对应,很多很多语言都是静态的,比如 C、JAVA、C#、C++等等,它们的特点是要强制确定变量类型。
// C
int a = 1;
一、慢性毒药——类型检查
静态类型的语言中,每个类型检查在编译期就已经确定了;而python在运行过程中才会确定类型,而且每次变量被访问,都需要确定当前类型才能进一步执行,这都需要 CPU 参与进来。
这就像两种流水线,一条静态类型的流水线仅需要一次检查即可;另一条动态类型的流水线,每次货物来了都需要安排人去检查,这肯定会影响性能。
不同的流水线工作方式
特别是在密集的计算过程中,会进行大量的 类型检查,那么计算性能就会变得很差,这就是为什么很多计算库都通过 C、C++或其它编译型静态语言 来实现的重要原因。
二、优化壁垒——无法进行静态优化
静态类型的语言可以通过一些手段,来优化代码,以此来提升程序的性能,比如 循环展开、死代码消除、常量传播等。
但是动态类型的语言就很难做到提前优化来提升性能,它必须在运行期间才能知道类型,就没法做到以上的那些操作。
这就像静态类型语言在考试前先把试卷的 所有问题看一遍,然后再做答;但动态类型语言就像真正的 闭卷考试,所有问题只有答题时才能知道。
提前知道考题,做题速度当然快
三、天生的胖子——内存开销大
静态类型的语言,丁是丁,卯是卯,一个 int 类型该是4字节就是4字节。
但python的动态类型可不是,要知道python是一个 纯面向对象 的语言,所有东西都是对象,它并不是纯粹的数据类型,这将消耗额外的内存来存储对象。
这就说明python是天生的胖子,它的内存消耗天然就是要大。
python天然的内存消耗大
四、优化思路
4.1 使用JIT编译器
我们可以用 JIT技术 来运行程序,提高性能,比如 PyPy,下载后直接用它进行运行:
pypy your_script.py
关于JIT技术本文不阐述,以后再开篇文章来说!
4.2 计算密集型使用性能更佳的库
当你需要执行大量计算,不要使用python原生的计算方式,采用 numpy、scipy 等库来执行将跳过动态类型检查,提升性能。
4.3 使用静态类型语言开发结合python
这个操作适合大佬,直接使用 Cython 来开发,结合python使用。
五、总结
很多人看到这里可能都不敢用python了,其实不用担心,我们一般情况下是用不到性能瓶颈的,依赖于现在日益强大的硬件,很多程序都能流畅运行。
动态类型虽然性能上打了折扣,但是实在在提高了开发效率,能够更加快速地实现我们的想法,正所谓 鱼和熊掌不可兼得,有牺牲肯定有回报。