为python加速

本来我一直不知道怎么来更好地优化网页的性能,然后最近做python和php同类网页渲染速度比较时,意外地发现一个很简单很白痴但是 我一直没发现的好方法(不得不bs我自己):直接像某些php应用比如discuz论坛那样,在生成的网页中打印出“本页面生成时间多少多少秒”,然后在 不停地访问网页测试时,很直观地就能发现什么操作会导致瓶颈,怎样来解决瓶颈了。

于是我发现simplecd在 生成首页时,意外地竟然需要0.2秒左右,真真不能忍:对比discuz论坛首页平均生成才0.02秒,而discuz论坛的首页页面无疑比 simplecd的主页要复杂不少;这让我情何以堪啊,因为这必然不是python语言导致的差距,只能说是我完全没做优化而discuz程序优化得很好 的后果。

其实不用分析也能知道肯定是数据库在拖累,simplecd在生成首页时需要在sqlite的三个数据库中进行42多次查询,是历史原因导致的极其低效的一个设计;但是这40多次查询中,其实大部分是非常快的查询,仔细分析一下就有两个是性能大户,其他都不慢。

第一个大户就是:获取数据个数

select count(*) from verycd

这个操作每次都要花不少时间,这是因为每次数据库都要锁住然后遍历一遍主键统计个数的缘故,数据量越大耗时就越大,耗时为o(n),n为数据库大小;实际 上解决这个问题非常容易,只要随便在哪存一个当前数据的个数,只有在增删数据的时候改动就行了,这样时间就是o(1)的了

第二个大户就是:获取最新更新的20个数据列表

select verycdid,title,brief,updtime from verycd order by updtime desc limit 20;

因为在updtime上面做了索引,所以其实真正查询时间也就是搜索索引的时间而已。然则为什么这个操作会慢呢?因为我的数据是按照publish time插入的,按update time进行显示的话就肯定需要在至少20个不同的地方做i/o,这么一来就慢了。解决的方法就是让它在一个地方做i/o。也就是,除非数据库加入新数据 /改变原有数据,否则把这条语句的返回结果缓存起来。这么一来又快了20倍:)

接下来的是20条小case:取得发布人和点击数信息

select owner from lock where 127.0.0.1:11211′], debug=0)

memcache其实就是一个map结构,最常使用的就是两个函数了:

第一个就是set(key,value,timeout),这个很简单就是把key映射到value,timeout指的是什么时候这个映射失效

第二个就是get(key)函数,返回key所指向的value

于是对一个正常的sql查询可以这么干

sql = ‘select count(*) from verycd’c = sqlite3.connect(‘verycd.db’).cursor() # 原来的处理方式c.execute(sql)count = c.fetchone()[0] # 现在的处理方式from hashlib import md5key=md5(sql)count = mc.get(key)if not count: c.execute(sql) count = c.fetchone()[0] mc.set(key,count,60*5) #存5分钟

其中md5是为了让key分布更均匀,其他代码很直观我就不解释了。

优化过语句1和语句2后,首页的平均生成时间已经降低到0.02秒,和discuz一个量级了;再经过语句3的优化,最终结果是首页生成时间降低到了0.006秒左右,经过memcached寥寥几行代码的优化,性能提高了3300%。终于可以挺直腰板来看discuz了)

Posted in 未分类

发表评论