{人面不知何去处 桃花依旧笑春风}

python PerformanceTips

Posted in Uncategorized by interma on 2013/06/21

原文:http://wiki.python.org/moin/PythonSpeed/PerformanceTips
给自己做的笔记。

1,方法论
Get it right.
Test it’s right.
Profile if slow.
Optimise.
Repeat from 2.
2,选择合适的数据结构
3,sort小技巧:按某一维排序

def sortby(somelist, n):
    nlist = [(x[n], x) for x in somelist]
    nlist.sort()
    return [val for (key, val) in nlist]
def sortby_inplace(somelist, n):
    somelist[:] = [(x[n], x) for x in somelist]
    somelist.sort()
    somelist[:] = [val for (key, val) in somelist]
    return
//py2.4+
n = 1
import operator
nlist.sort(key=operator.itemgetter(n))

另外:sort()操作是稳定的。
From Python 2.3 sort is guaranteed to be stable.
(to be precise, it’s stable in CPython 2.3, and guaranteed to be stable in Python 2.4)
4,字符串拼接
多用join和位置参数替换

slist = [some_function(elt) for elt in somelist]
s = "".join(slist)
out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)

避免+拼接产生的多个临时对象。
5,循环
多使用内置循环函数(如map):

newlist = []
for word in oldlist:
    newlist.append(word.upper())
newlist = [s.upper() for s in oldlist]
newlist = map(str.upper, oldlist)

map也许对应了一个较优化的字节码。
6,避免名字查找(个人不提倡)

upper = str.upper
newlist = []
append = newlist.append
for word in oldlist:
    append(upper(word))

其实就是避免多次指针查询,而直接访问对应的locals()字典。
这是以牺牲可读性为代价的,个人觉得为了这一点点性能提升,完全没必要。
7,字典默认值

wdict = {}
get = wdict.get
for word in words:
    wdict[word] = get(word, 0) + 1

8,用xrange替代range
避免内存短爆,xrange is a generator object。
generator object记忆了内部变量和控制流为下次调用使用,基础是yield操作符。
记住控制流挺不寻常,以后要了解一下其内部实现
9,profile工具
直接使用标准库中的profiling modules即可。
业务代码其实打点日志就行了,用不上profile工具。
原文中还介绍了几个工具
10,总结
一句话:严格遵守方法论,选对数据结构,记住join和xrange。
这基本就够用了~

Tagged with: ,

py3源码[7]-内存管理与垃圾收集

Posted in Uncategorized by interma on 2013/06/06

这块暂时只记录了py2.5的实现方式,尚未对照py3是否有变动。

一,内存管理

1,总体层次:type级(freelist);object级(关键);底层(clib:malloc/free)。

2,object级详解:

a,申请小内存(<256byte)时,采用内存池方式分配。否则直接malloc。

b,内存池层次:arenas->arena->pool->block,见下图

c,每个arena空间为定长256kb(具有一个arena_object头,图中未画出),存储着若干个pool;单个pool一般为页大小(4K),内联pool-header描述,存储某个定长(8Nbyte,max 256byte)的block;1个block为最小内存分配单位。

d,usedpools链表,用大小作为索引,串着同一个block大小的各个pool,作为分配总入口来加速分配。

e,一个arena空间都空闲的时候,是可以被收回的(>=py2.5,老版本存在内存泄漏)。

二,垃圾收集(GC)

1,引用计数+mark-sweep垃圾收集。为啥混合使用引用计数呢?这里有当时的设计思路

2,引用计数:实现简单;具有实时性;对程序性能冲击小;垃圾收集:只针对容器对象(class,list,dict等),只处理循环引用。

3,垃圾收集三色标记,分代(3)收集,采用链表阈值触发收集,其中含有_del_方法的对象会导致内存泄漏。

Tagged with: