一次优化web项目的经历记录(三)
一次优化web项目的经历记录
这段时间以来的总结与反思
前言:最近很长一段时间没有更新博客了,忙于一堆子项目的开发,严重拖慢了学习与思考的进程。
开水倒满了需要提早放下杯子,晚了就会烫手,这段时间以来,写的东西越来越不严谨,各种低级错误频出,早该停下总结并巩固一下了。
但出于一些原因一直没付诸于行,终于,烫到手了
第三章:yield与generator
Footprint.get_pics() 里到底发生了什么呢?
抱歉,最近事情有点多,更新晚了,我们继续。get_pics 本身耗时100多s,然而其内部的几个函数耗时加起来居然远低于这个值,为什么呢?
我就不绕弯了,答案就是本章的标题,yield与generator。我是怎么确定的呢?因为目前还剩下的 get_pics 内部的仅有的几个方法里,最可疑的只有这个方法:iter_directory
iter_directory 是用来迭代阿里云oss上的某个目录(其实是前缀相同的所有对象),以得到其中的所有文件(对象)的。很显然,这个方法需要调用外部api!
而作为一个调用外部api的方法,其执行2679次的总耗时居然仅有0.03秒,我的天哪,怎么可能!
是我的监听器有什么漏洞吗?
按照我的代码逻辑,在某个被注册的方法进入前,将会获取当前时间戳一次,而在其退出后则立即得到时间差,累加进方法总耗时。
我们不妨假设这样一种情景:有一个方法f,其返回值为方法g。g不会在f内部得到执行,它仅仅被返回,并且在f外部被调用并执行,用python描述如下:
@monitor.register
def f():
def g():
pass
return g
...
if __name__ == '__main__':
g = f()
for _ in range(0, 1000):
g()
print monitor.report()
那么很显然的,我的监听器实际上只监听了f方法的执行总耗时,而g的执行发生在f之外,成功“逃脱”了我的监视。
上面这个假设与yield有什么关系呢?
def f():
print '2'
yield 'f'
print '3'
if __name__ == '__main__':
print '1'
f()
print '4'
来猜测一下,上面的几个数字的打印顺序是什么呢?1234?如果你这么认为,那或许你需要补一补迭代器的常识了:
正确的答案应该是14。是的,没有2,也没有3。当你执行 f() 时,函数 f 根本没有得到真正的调用!准确的说,函数 f 其实被调用了,但这个 f 却不是你说认识的 f!
是的,当函数或方法内部使用了yield关键字时,实际上它已经不再是它自己了。当你执行 f() ,真正发生的并不是 f 内部的东东顺序执行,而是构造了一个 迭代器。
只有你执行 f().next(),也就是在返回的迭代器上执行 next() 方法,代码才会从f 内部开始解释执行,知道遇到yield关键字并立即返回。
再次执行 next() 时,会从上次离开的地方继续。如果遇不到yield了,则已迭代完毕,抛出一个 StopIteration 。
现在真相大白了, iter_directory 这个方法就是造成瓶颈的真凶。很显然,由于 iter_directory 事实上是一个generator,注册它其实是监听了它的迭代器生成方法。得到的耗时其实仅仅是生成迭代器的耗时。
真正造成严重延时的真凶,就是访问阿里云oss查找对象的方法,而这个操作是虽然看似在 iter_directory 里,但其实是在它的迭代器构造方法之外的,所以检测不到。
接下来就没什么好说的了,找到了耗时的真凶就该对它做优化了。这很容易,我采取了缓存策略,从memcache上获取缓存的值,而不是每次都从阿里云里去查找,除非接到更新信号或memcache上的值为空。
这次的事故中我学到了什么呢?
首先是,自己留下的坑总会自己跳。当初学python时,对yield的理解仅限于迭代器模式的一种语法糖,而没有深刻的去了解其实现的机制,没有认识到其对原函数|方法的装饰改造效果。于是就有了这次的不愉快的踩坑经历。
其次,疲劳代码很容易出错。无论怎么想,我也不明白自己当初怎么会写出类似于“每次需要某值都遍历某树”这种可谓脑残低效至极的代码,唯一的解释就是累了,没有仔细思考布局。
甚至类似的地方,在这次优化过程中还发现了很多处,虽然最终验证影响都远不如这个地方那么大,但看着自己写出的这么糟糕的代码还是很让人不爽的。真希望抛开一切来一次大重构。
最后,定期的总结思考很重要。这次的问题最直接的原因其实还不是对yield理解不透彻,虽然这是个隐患,但这次的导火索是在阿里云对象存储这块的糟糕的设计。
以前只是简单的用过阿里云oss服务,而最近的几个项目却恰好都深度依赖于它。但由于几个项目时间都赶得比较紧,在阿里云oss这块就只能调通能用就过。
内心恐怕早也意识到oss这块需要好好设计设计,规划一下了,但毕竟还是偷懒了。这次这个项目暴露出的之前设计上的不合理真的很重要,它直接改变了我对下一个项目(素材发布共享平台)的结构的设计。
很难想象如果再晚点发现,当这一套糟糕的模型已经用在多个项目中后,会有多麻烦。
本系列到此结束,谢谢
一次优化web项目的经历记录(三)的更多相关文章
- 一次优化web项目的经历记录(二)
一次优化web项目的经历记录 这段时间以来的总结与反思 前言:最近很长一段时间没有更新博客了,忙于一堆子项目的开发,严重拖慢了学习与思考的进程. 开水倒满了需要提早放下杯子,晚了就会烫手,这段时间以来 ...
- 一次优化web项目的经历记录(一)
一次优化web项目的经历记录 这段时间以来的总结与反思 前言:最近很长一段时间没有更新博客了,忙于一堆子项目的开发,严重拖慢了学习与思考的进程.开水倒满了需要提早放下杯子,晚了就会烫手,这段时间以来, ...
- Java Web项目搭建过程记录(struts2)
开发工具:eclipse 搭建环境:jdk1.7 tomcat 8.0 基础的java开发环境搭建过程不再赘述,下面从打开eclipse 之后的操作开始 第一步: 创建项目,File -> ...
- windows系统中ubuntu虚拟机安装及web项目到服务上(三)
项目在ubuntu虚拟机下的部署 一:将war从本地通过Xftp 4 传到虚拟机tomcat目录下的webapps目录下 2:修改tomcat下的server.xml <Host name=& ...
- 用maven工具管理web项目的错误记录:org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException
运行异常报告日志: 严重: Context initialization failedorg.springframework.beans.factory.xml.XmlBeanDefinitionSt ...
- 小白的首个maven web项目Step1软件安装三(8.0.15mysql及workbench安装)
直接先开始下 MySQL 和 Workbench(mysql的可视化工具) ,注意下得是镜像版 .msi 后缀的 (mysql是纯控制面板的呈现方式,想要界面化操作可以装可视化工具,这里我装的是wor ...
- 部署WEB项目到服务器(三)安装mysql到linux服务器(Ubuntu)详解
突发奇想,想在自己电脑上部署一个web网站. 1,首先是下载一个适合自己已安装服务器版本的mysql数据库. 这里使用网上的链接http://dev.mysql.com/downloads/mysql ...
- mave之:java的web项目必须要的三个jar的pom形式
jsp-api javax.servlet-api jstl <!-- jsp --> <dependency> <groupId>javax.servlet< ...
- eclipse修改web项目部署路径
Eclipse中用Tomcat发布的Web项目,更改其部署路径 我的Eclipse的工作目录是D:/workspace 先配置Tomcat 选择你的tomcat版本 点击next 这里先不要把项目添加 ...
随机推荐
- ASP.NET MVC轻教程 Step By Step 6——改进表单
上一节我们使用原始的HTML表单来完成留言功能,但是ASP.NET MVC提供了丰富的HTML辅助方法来帮助我们构建更简洁优雅的表单. Step 1. 修改Form标签 首先,我们可以使用Html.B ...
- jsonp跨域问题记录
这段时间用H5做移动app开发,遇到不少之前做web的时候不曾遇到的问题,记录一下,共勉-- 首先说一个:js跨域取数的问题 描述: 之前做web都是通过后台获取数据,没考虑过跨域的问题.这次用h5 ...
- 【产品对比分析】See做了明星衣橱想做的东西?
不断地发现.联想.思考,让学到的东西互通起来吧! 先来两张See的界面图镇楼—— See简介: See是一个专注找同款的时尚社区,主打功能是一键拍照找同款,由社区为你提供最佳商品或 ...
- BZOJ 1002 轮状病毒
Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同的n轮状病毒数输出 Sample Inpu ...
- SQL servere 范式、事务
一.数据库范式: 1.构造数据库必须遵循一定的规则.在关系数据库中,这种规则就是范式. 范式是符合某一种级别的关系模式的集合.数据库中的关系必须满足一定的要求,即满足不同的范式. 满足最低要求的范式是 ...
- Oracle RAC学习笔记:基本概念及入门
Oracle RAC学习笔记:基本概念及入门 2010年04月19日 10:39 来源:书童的博客 作者:书童 编辑:晓熊 [技术开发 技术文章] oracle 10g real applica ...
- bzoj1257
这道题初看确实没什么思路,感觉之前的数论知识都用不上,只好自己找规律首先当n>=k 这部分是很容易直接算出的下面我们先来尝试这穷举i,不难发现当穷举i时,总存在一段连续的除数,k div i=p ...
- poj3373
其实这道题只告诉了一个事当出现多个满足答案约束条件是,我们可以求一个再求一个,不要一下子全求完前两个条件怎么弄之前已经做过类似的了于是我们可以用记忆化搜索找出最小差异然后配合最小差异来剪枝,搜索出最小 ...
- BZOJ1699: [Usaco2007 Jan]Balanced Lineup排队
1699: [Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 933 Solved: 56 ...
- mysql 学习(1)
1.从图中看到mysql是客户服务器模式. 2.我们如何操纵数据库? a.直接sql,各种编程语言, 3.客户端和服务器如何通信呢? 凡是c/s模式的都会自己的协议,但是都是基于TCP/IP协议,在l ...