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

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: ,

后端服务程序优化

Posted in Uncategorized by interma on 2013/03/08

参考xiaowei PPT整理。

one rule:没有前提假设,就没有优化方案。

一,内存分配+多线程算法
问题,@glibc
1,多线程分配慢:为了线程安全,加lock;线程级缓存内存,tcmalloc
2,碎片化:直接划出一块慢慢切分。

解决方法
3,短生命周期Vs长生命周期:如php,不需要太精巧的分配手段。
4,定长分配:freelist。
5,变长分配:多级定长池,巨大内存直接malloc。
6,常用数据结构优化:
a,hash:节点空间连续化(写不友好)
b,链表:类似hash,连续化,少用next指针。
c,动态数组:1维转2维,随用新增。
7,内存回收:
延时释放,依赖工程经验。
小tip:48bit指针,16bit引用计数,配合内存池。
8,实例:
一写多读线程安全链表:依赖next指针的调整顺序,lock-free,CAS。
多写多读hash表:由如上链表组成,针对每个slot设置锁,写冲突概率低。但是锁内存开销大,可以多个slot映射到一个锁来节省空间。多线程下性能佳。

二,磁盘io
传统硬盘原理:seek+r/w,目标:减少seek时间。
应用缓存->系统缓存->物理硬盘。
1,流式io:buf,如fwrite。用户层程序crash时的数据一致性问题。
2,底层io:如write。OS crash。
3,直接io:direct io。机器crash。

分布式存储系统:性能,数据备份。对事务支持困难。

三,网络io
实时性vs并发性。
同步模型:io和逻辑皆同步,epoll句柄池中取句柄(可读/写)->线程同步处理。有可能被r/w阻塞。
半同步半异步模型:折中选择,句柄池中取句柄(读/写完毕,数据ready)->线程同步处理。时效性稍差(数据ready,处理逻辑不足)
全异步模型模型:高性能,避免网络r/w io和磁盘io,io状态机。不提供同步语义。举例:
3级流水线框架:网络,CPU,磁盘。每级多个并发处理单元。
目标:避免某级空等。需要合理调度。

几个小tips:
1,长连接性能优于短链接。
2,留意短链接时的timewait。
3,不连续内存读写:readv,writev,节省内存cp。
4,同台机器,使用domain socket避免流量过网卡:如2个交互程序部署在一台机器上,原理:shm。

Tagged with: ,