python-面向运行时性能优化

python-面向运行时性能优化

一: python运行机制

1> 语言运行过程

1. 高级语言分类及特点

A: 分类

高级语言-程序的执行方式 分类:编译型语言、解释型语言;

分类 含义
编译型语言 将所有源代码一次性转换成二进制指令,也就是生成一个可执行程序(如Windows 下的 .exe),比如C语言、C++、Golang、Pascal(Delphi)、汇编等;
解释型语言 一边执行一边转换,需要哪些源代码就转换哪些源代码,不生成可执行程序,比如 Python、JavaScript、PHP、Shell、MATLAB 等
半编译半解释型语言 既用了解释器也用编译器,如 Java 和 C## 。源代码需要先转换成一种中间文件(字节码文件),然后再将中间文件拿到虚拟机中执行

使用的转换工具称为 :编译器
编译器的类型:前端编译器、后端编译器

编译器分类 含义
前端编译器 编译器的分析阶段也称为前端,它将程序划分为基本的组成部分,检查代码的语法、语义和语法,然后生成中间代码。分析阶段包括词法分析、语义分析和语法分析
后端编译器 编译器的合成阶段也称为后端,优化中间代码,生成目标代码。合成阶段包括代码优化器和代码生成器
B: 特点
编译型语言 特点
1 编译型语言经过编译器转成可执行程序后,可执行程序里面包含的就是机器码。只要拥有可执行程序,可以随时运行,不用再重新编译,即 一次编译,无限次运行;
2 编译型语言可以脱离开发环境运行;运行可执行程序时,不再需要源代码和编译器
3 编译型语言一般不能跨平台,即不能在不同的操作系统之间随意切换
解释型语言 特点
1 解释型语言,每次执行程序都需要一边转换一边执行
2 无法脱离开发环境,所以解释型语言的执行效率天生就低于编译型语言,甚至存在数量级的差距
3 解释型语言 能跨平台,即实现“一次编写,到处运行
C: 对比
类型 原理 优点 缺点
编译型语言 通过专门的编译器,将所有源代码一次性转换成特定平台(Windows、Linux 等)执行的机器码(以可执行文件的形式存在) 编译一次后,脱离了编译器也可以运行,并且运行效率高 可移植性差,不够灵活
解释型语言 由专门的解释器,根据需要将部分源代码临时转换成特定平台的机器码 跨平台性好,通过不同的解释器,将相同的源代码解释成不同平台下的机器码 一边执行一边转换,效率很低

2. python 运行过程

在这里插入图片描述
理解:

注释 理解
运行过程 C、C++等语言都是:先经过预处理、编译、汇编、链接、最终生成机器代码(可执行文件)。而python每次运行,多了中间的两步(编译、解释)
.pyc文件存在的目的 .pyc是PyCodeObject的一种永久保存方式,对可能重用的模块不用再重新解释,提高程序运行速度

2> python 内存管理机制

python的自动垃圾回收机制,在Python中创建对象时无须手动释放。这对开发者非常友好,让开发者无须关注低层内存管理;

1. 垃圾回收算法

在python中,垃圾回收算法以引用计数为主,标记-清除和分代收集两种机制为辅;

A: 引用计数
原理 理解
1 每个对象有一个整型的引用计数属性。用于记录对象被引用的次数
2 例如对象A,如果有一个对象引用了A,则A的引用计数+1
3 当引用删除时,A的引用计数-1
4 当A的引用计数为0时,即表示对象A不可能再被使用,直接回收

demo
Python中,可以通过sys模块的getrefcount函数获取指定对象的引用计数器的值,

import sys
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:

    def __init__(self):
        self.__age = 20

    def name(self, firstName, lastName):
        return firstName + ' ' + lastName

    def age(self):
        return self.__age

    @staticmethod
    def class_name():
        return People.__name__

print("创建对象 0 + 1 =", sys.getrefcount(People()))
P = People()
print("创建对象 1+ 1 =", sys.getrefcount(P))
A = P
a = A
print("创建对象 2+ 2 =", sys.getrefcount(a))
print("创建对象 2+ 2 =", sys.getrefcount(P))
print("创建对象 2+ 2 =", sys.getrefcount(A))
a = None
print("创建对象 4 -1 =", sys.getrefcount(P))
print("创建对象 4 -1 =", sys.getrefcount(A))
del A
print("创建对象 3 -1 =", sys.getrefcount(P))
list_P = [P, P, P]
print("P 三次加入列表被调用;创建对象 2 + 3 =", sys.getrefcount(P))
========================
创建对象 0 + 1 = 1
创建对象 1+ 1 = 2
创建对象 2+ 2 = 4
创建对象 2+ 2 = 4
创建对象 2+ 2 = 4
创建对象 4 -1 = 3
创建对象 4 -1 = 3
创建对象 3 -1 = 2
P 三次加入列表被调用;创建对象 2 + 3 = 5



优点&缺点

引用计数 含义
优点 1, 高效、逻辑简单,只需根据规则对计数器做加减法;2,实时性。一旦对象的计数器为零,就说明对象永远不可能再被用到,无须等待特定时机,直接释放内存。
缺点 1, 需要为对象分配引用计数空间,增大了内存消耗;2, 当需要释放的对象比较大时,如字典对象,需要对引用的所有对象循环嵌套调用,可能耗时比较长;3, 循环引用。这是引用计数的致命伤,引用计数对此是无解的,因此必须要使用其它的垃圾回收算法对其进行补充
B: 标记清除

标记-清除算法:主要用于潜在的循环引用问题;

序列 算法步骤
1 标记阶段。将所有的对象看成图的节点,根据对象的引用关系构造图结构。从图的根节点遍历所有的对象,所有访问到的对象被打上标记,表明对象是“可达”的;
2 清除阶段。遍历所有对象,如果发现某个对象没有标记为“可达”,则就回收;

demo

class A():
    def __init__(self):
        self.obj = None


def func():
    a = A()
    b = A()
    c = A()
    d = A()

    a.obj = b
    b.obj = a
    return [c, d]


e = func()

上面代码中,a和b相互引用,e引用了c和d。整个引用关系如下图所示:
在这里插入图片描述
如果采用引用计数器算法,那么a和b两个对象将无法被回收。而采用标记清除法,从根节点(即e对象)开始遍历,c、d、e三个对象都会被标记为可达,而a和b无法被标记。因此a和b会被回收;

标记清除流程
在这里插入图片描述
标记清除缺点:执行效率低,且会造成空间碎片问题;

C: 分代回收

分代回收原理:在执行垃圾回收过程中,程序会被暂停,即stop-the-world;
为了减少程序的暂停时间,采用分代回收(Generational Collection)降低垃圾收集耗时

解决标记清除扫描遍历开销大,效率低的问题;
将对象分为初生代、中生代、老生代,设置阈值来扫描遍历的类型,以空间换取时间;

分代回收法则

序列 含义
1 接大部分的对象生命周期短,大部分对象都是朝生夕灭
2 经历越多次数的垃圾收集且活下来的对象,说明该对象越不可能是垃圾,应该越少去收集

分代回收理解

序列 含义
1 对象刚创建时为G0。
2 如果在一轮GC扫描中存活下来,则移至G1,处于G1的对象被扫描次数会减少。
3 如果再次在扫描中活下来,则进入G2,处于G1的对象被扫描次数将会更少

在这里插入图片描述

触发GC时机

当某世代中分配的对象数量与被释放的对象之差达到某个阈值的时,将触发对该代的扫描。当某世代触发扫描时,比该世代年轻的世代也会触发扫描;

import gc
threshold = gc.get_threshold()
print("各世代的阈值:", threshold)

# 设置各世代阈值
gc.set_threshold(800, 20, 20)
D: 内存池

python 内存池机制:为了避免频繁的申请和释放内存,python的内置数据类型,数值、字符串,查看python源码可以看到数值缓存范围为 -5 ~ 257;对于 -5 ~ 257 范围内的数值,创建之后python会把其加入到缓存池中,当再次使用时,则直接从缓存池中返回,而不需要重新申请内存,如果超出了这个范围的数值,则每次都需要申请内存;这样能够减少内存碎片,提升效率;
python内置对象(int,dict,list,str等)都有独立的私有内存池,对象之间的内存池不共享;

内存池分类

分类 理解
大内存 以256Bytes 为界限,大于256Bytes 属于大内存,大内存使用Malloc进行分配,
小内存 以256Bytes 为界限,小于256Bytes 属于小内存,小内存使用内存池进行分配;

内存池分别level
python 的对象管理主要位于Level+1 —> Level+3 层;从内存池申请的内存对象被删除后的内存会被归还到内存池,避免了多次频繁释放,能有效减少内存碎片的产生;

level 理解
Level+1 大于256Bytes 属于大内存,使用Malloc进行分配
Level+2 小于256Bytes 属于小内存,由python 对象分配器(内存池)分配;
Level+3 python内置对象(int,dict,list,str等)都有独立的私有内存池,对象之间的内存池不共享;
E: 缓存池

python 缓存池作用:

作用 理解
1 提升运行效率,对常用对象缓存;
2 小整数对象池,intern,常量池和free_list

在这里插入图片描述

3> python 常用解释器

分类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python 3.8.10-amd64是Python编程语言的一个版本,其中"3.8.10"表示Python的主要版本号为3.8,而"amd64"表示该版本适用于64位的Windows操作系统。 Python是一种高级编程语言,具有简单易学、可读性高和灵活性的特点。它被广泛用于各种领域,包括软件开发、数据分析、人工智能、网络开发等。 Python 3.8.10-amd64是Python 3.8系列的一个小版本更新,主要针对安全性和稳定性做了一些改进和修复。在这个版本中,开发者修复了一些已知的漏洞和错误,并进行了一些性能优化。 Python 3.8.10-amd64可以在64位的Windows操作系统上运行。"amd64"代表Advanced Micro Devices 64位架构,是一种64位x86处理器架构,常用于PC、服务器和一些嵌入式系统。 使用Python 3.8.10-amd64,开发者可以编写各种应用程序,从简单的脚本到复杂的桌面应用程序或者Web应用程序。Python具有丰富的库和模块,可以方便地完成各种任务,还支持面向对象编程、函数式编程等多种编程范式。 Python 3.8.10-amd64的发布说明中详细列出了所有的改进和修复,用户可以参考该文档了解具体的更新内容。为了正常使用Python 3.8.10-amd64,用户需要下载安装对应的Python安装包,并按照安装指南进行安装和配置。 总之,Python 3.8.10-amd64是Python编程语言的一个版本,适用于64位的Windows操作系统,具有改进和修复的功能,可以帮助开发者快速、高效地进行软件开发与应用。 ### 回答2: Python 3.8.10是Python编程语言的一个版本,而`amd64`是指该版本适用于64位的x86架构。本版本是Python 3.8的一次更新,修复了一些bug并引入了一些新特性。 Python 3.8.10增强了Python的性能、安全性和稳定性。对于已知的错误进行了修复,提高了代码的运行效率和可靠性。这些修复使得Python更加健壮,同提供了更好的用户体验。 在这个版本中,Python 3.8.10引入了一些新特性。例如,它支持使用Python的`f-strings`格式化字符串,这使得代码更加易读和简洁。它还改进了Python的类型提示功能,帮助开发者更好地理解代码和进行调试。 除了这些改进,Python 3.8.10还修复了一些已知的安全问题和漏洞,提高了Python的安全性。这些修复保护了用户的数据和系统免受潜在的威胁和攻击。 总之,Python 3.8.10是Python编程语言的一个版本,它提供了一些新特性、修复了已知的错误并增强了性能、安全性和稳定性。这个版本适用于64位的x86架构,在使用Python进行开发可以选择安装和使用。 ### 回答3: Python-3.8.10-amd64是Python编程语言的一个版本。它是Python 3.8系列的第10个维护版本,特别为64位的x86架构的计算机设计。 Python是一种高级、面向对象、解释性的编程语言,具有简洁而易读的语法。Python-3.8.10-amd64版本包含了许多改进和修复的错误,以提升语言的性能和稳定性。 在Python 3.8.10-amd64中,改进的重点是修复了各种错误和漏洞,以提高整体的可靠性。此外,该版本也引入了一些小的新功能和改进,以增强开发者的体验。 与以前的版本相比,Python-3.8.10-amd64在性能和资源利用方面进行了优化。这个版本还修复了一些安全性问题,提升了编程环境的安全性。 总之,Python-3.8.10-amd64是Python 3.8系列的一个稳定版本,包含了许多改进和修复错误的功能。它为64位的x86计算机提供了更好的性能和稳定性,同还增加了一些新的功能和改进。如果你是Python开发者,升级到这个版本可能会带来更好的开发体验和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

45度看我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值