前言
可以使用 Cython, PyPy提升 python的速度
Cython
Cython是让Python脚本支持C语言扩展的编译器, Cython能够将Python+C混合编码的.pyx脚本转换为C代码, 主要用于优化Python脚本性能或Python调用C函数库。由于Python固有的性能差的问题, 用C扩展Python成为提高Python性能常用方法, Cython算是较为常见的一种扩展方式。
推荐文章:
https://www.jianshu.com/p/fc5025094912
https://www.cnblogs.com/yafengabc/p/6130849.html
https://baijiahao.baidu.com/s?id=1606135207446878267&wfr=spider&for=pc
https://baijiahao.baidu.com/s?id=1606135207446878267&wfr=spider&for=pc
CPython 与 PyPy
CPython: 是用C语言实现Python, 是目前应用最广泛的解释器。最新的语言特性都是在这个上面先实现的, 基本包含了所有第三方库支持, 但是CPython有几个缺陷, 一是全局锁使Python在多线程效能上表现不佳, 二是CPython无法支持JIT(即时编译), 导致其执行速度不及Java和Javascipt等语言。于是出现了Pypy。
Pypy: 是用Python自身实现的解释器。针对CPython的缺点进行了各方面的改良, 性能得到很大的提升。最重要的一点就是Pypy集成了JIT。但是, Pypy无法支持官方的C/Python API, 导致无法使用例如Numpy, Scipy等重要的第三方库。这也是现在Pypy没有被广泛使用的原因吧。
PyPy与CPython的不同
- CPython是使用解释执行的方式, 这样的实现方式在性能上是很凄惨的。
- 而PyPy使用了JIT(即时编译)技术, 在性能上得到了提升。
Python的解释器:
由于Python是动态编译的语言, 和C/C++、Java或者Kotlin等静态语言不同, 它是在运行时一句一句代码地边编译边执行的, 而Java是提前将高级语言编译成了JVM字节码, 运行时直接通过JVM和机器打交道, 所以进行密集计算时运行速度远高于动态编译语言。
PyPy, 它使用了JIT(即时编译)技术, 混合了动态编译和静态编译的特性, 仍然是一句一句编译源代码, 但是会将翻译过的代码缓存起来以降低性能损耗。相对于静态编译代码, 即时编译的代码可以处理延迟绑定并增强安全性。绝大部分 Python代码都可以在PyPy下运行, 但是PyPy和CPython有一些是不同的。
一个速度比较例子
使用C++和Python分别实现目录大小计算的算法。
其中的要求是:
- 计算单个目录大小, 返回一个数值
- 计算目录及目录下所有子目录大小, 返回一个map表
结果比较
Python的运行结果
单纯看Python的结果, 可以看出来线程池的优化大大提高了递归计算的速度, 将近提升了10倍的效率
C++的运行结果
通过比较单个目录大小计算, C比Python快了近5.6倍
而计算所有目录大小, C比Python快了近5.6倍
说明
线程池的池子大小设为5。
计算的目录都是E:\1Code\Repositories
, 5.8G的大小
为了避免全局线程池影响到其他函数的运行效率, 线程池实现的方法 单独运行
两者的实现算法都是一致的
Python实现了4种方法
- 第一种是使用
os.walk
的生成器来遍历计算单个目录大小, 名为get_dir_size
- 第二种是递归计算单个目录大小, 名为
get_dir_size_recursive
- 第三种是递归计算目录及目录下所有子目录大小, 名为
get_all_dir_size
- 第四种是线程池+递归计算目录及目录下所有子目录大小, 名为
get_all_dir_size_thread
C++实现了2种方法
- 第一种是递归计算单个目录大小, 名为
SimpleGetDirectorySizeRecursive
- 第二种是递归计算目录及目录下所有子目录大小, 名为
SimpleGetDirectorySize
Python的实现
1 | import os |
C++的实现
1 |
|