- 内容提要
- 前言
- 作者简介
- 封面简介
- 第1章 理解高性能 Python
- 第2章 通过性能分析找到瓶颈
- 2.1 高效地分析性能
- 2.2 Julia 集合的介绍
- 2.3 计算完整的 Julia 集合
- 2.4 计时的简单方法——打印和修饰
- 2.5 用 UNIX 的 time 命令进行简单的计时
- 2.6 使用 cProfile 模块
- 2.7 用 runsnakerun 对 cProfile 的输出进行可视化
- 2.8 用 line_profiler 进行逐行分析
- 2.9 用 memory_profiler 诊断内存的用量
- 2.10 用 heapy 调查堆上的对象
- 2.11 用 dowser 实时画出变量的实例
- 2.12 用 dis 模块检查 CPython 字节码
- 2.13 在优化期间进行单元测试保持代码的正确性
- 2.14 确保性能分析成功的策略
- 2.15 小结
- 第3章 列表和元组
- 第4章 字典和集合
- 第5章 迭代器和生成器
- 第6章 矩阵和矢量计算
- 第7章 编译成 C
- 第8章 并发
- 第9章 multiprocessing 模块
- 第10章 集群和工作队列
- 第11章 使用更少的 RAM
- 第12章 现场教训
12.3 在 Lyst.com 的大规模产品化的机器学习
Sebastjan Trepca (lyst.com)
Lyst.com是一个位于伦敦的时尚推荐引擎,每个月有超过2 000 000个用户通过Lyst的艰苦抓取、清理和建模过程来学习到新时尚。它成立于2010年,得到了2 000万美元的融资。
Sebastjan Trepca是技术创立者和CTO,他使用Django创建了网站,Python已经帮助了团队来快速地测试新的想法。
12.3.1 Python在Lyst的地位
自从网站创建以来,Python和Django就已经是Lyst的核心了。随着内部的项目成长,一些Python组件被其他工具和语言取代来适应系统不断成熟的需求。
12.3.2 集群设计
集群运行于亚马逊的EC2上。总共有大约100台机器,包括更新的C3实例,具有良好的CPU性能。
Redis和PyRes一起作为队列来使用并存储元数据。主要数据格式是JSON,目的是让人易于理解。Supervisord让进程保持活跃。
Elasticsearch和PyES被用来索引所有的产品。Elasticsearch集群跨越7台机器存储了6千万个文档。Solr被调研过,但是因为缺少实时的更新特性而评价不高。
12.3.3 在快速前进的初创公司中做代码评估
写出能够被快速实现的代码更佳,这样一个商业上的想法就能够被测试了,而不是花费大量时间企图在第一遍就写出“完美的代码”。如果代码是有用的,那么它就能被重构;如果在代码背后的想法是糟糕的,那么删除并移除一个特性是代价低廉的。这可能导致一个复杂的基础代码,有许多对象传来传去,但是只要团队花费时间去重构对业务有用的代码,这就是可接受的。
文档字串(docstring)在Lyst中使用很多——尝试过一个外部的Sphinx文档系统但是放弃了,仅仅是为了方便阅读代码。一个维基被用来对过程和更大的系统做文档化。我们也开始创建很小的服务,而不是把一切都塞进一份基础代码中。
12.3.4 构建推荐引擎
首先推荐引擎用Python来编码,使用numpy和scipy来计算。接下来,推荐引擎的性能关键部分使用Cython来加速。核心的矩阵分解运算完全用Cython来写,产生了一个数量级的速度提升。这主要归因于有能力写出超过Python中的numpy数组的高效循环,当矢量化时,有些东西用纯粹的Python特别慢,性能糟糕,因为它需要numpy数组的内存拷贝。罪魁祸首就是numpy中的复杂索引,总是要对被切片的数组创建一份数据拷贝:如果数据拷贝不是必要的或者故意要做的,Cython的循环将会快得多。
随着时间的推移,系统的在线组件(负责在请求时执行推荐计算)被集成进了我们的搜索组件Elasticsearch中。在这个过程中,它们被翻译成了Java来允许与Elasticsearch做集成。这背后的主要原因不是因为性能,而是因为要让推荐引擎与一个完整而强大的搜索引擎做集成的用途,以允许我们更容易地把业务规则应用于所服务的推荐上来。Java组件本身就特别简单,并实现了主要的高效稀疏矢量内积。更复杂的离线组件还是用Python来写,使用了Python科学栈(主要是Python和Cython)的标准组件。
根据我们的经验,Python作为一种原型语言更有用:类似numpy、Cython和weave(更近的有Numba)这样可利用的工具允许我们在代码中的性能关键部分取得十分良好的性能,然而却还是保留了Python的干净和强大的表达力,而低级的优化将会事与愿违。
12.3.5 报告和监控
Graphite被用来做报告。当前,性能退化在部署之后能够用肉眼看到。这样就容易深入探查详细的事件报告或者缩小来看到站点行为的高层次报告并添加或者移除必要的事件。
一个为性能测试所做的更大的基础设施正在做内部设计。它将包括代表性的数据和用户场景来适当地测试新构建的站点。
一个作为脚手架的站点也会被用来让一小部分真正的访问者看到部署的最新版本——如果看到一个错误或者性能退化,那么它只会影响一小部分访问者,这个版本能够快速地回退。这将使得有错误的部署明显地降低成本并减少问题。
Sentry被用来记录和诊断Python的栈跟踪信息。
Jekins被用来和内存数据库配置做连续集成。这就能够做并行化的测试来让签入快速地暴露任何错误给开发者。
12.3.6 一些建议
有良好的工具来跟踪你所构建的东西的效能是真正重要的,并且在一开始是超级实用的。初创公司一直在变化并且工程不断地在演化:你从一个强烈探索性的阶段开始,用所有的时间构建原型并删除代码,直到你命中了金矿,然后你开始向更深处前进,提高代码和性能等。直到那时,一切都和快速迭代以及良好的监控/分析有关。我猜测这是重复了一遍又一遍的相当标准的建议,但是我想很多人没有真正体会到它是多么重要。
我不认为如今技术有多大影响,所以使用任何能为你工作的东西。然而在转移到类似AppEngine或者Heroku之类的寄宿环境之前,我要三思而行。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论