这是一篇(长)博文, 介绍了我们在 Repustate 迁移大量 Python/Cython 代码到 Go 语言的经验。如果你想了解整个故事,背景和所有的事情,请继续往下读。如果你只是想了解 Python 开发者在一头扎进 Go 语言前需要了解什么,请点击一下链接: 从Python迁移到Go的建议(Tips & Tricks)
背景在 Repustate,我们完成过的最棒的技术成就之一是实现了阿拉伯语的情感分析。阿拉伯语是一块难啃的硬骨头,因为它的词形变化相当复杂。比起譬如英语,阿拉伯语的分词(将一个句子切分呈几个独立的单词)也更困难,因为阿拉伯语的单词本身还可能会包含空白字符(例如:“阿列夫”在一个单词里的位置)。这也谈不上是泄密,Repustate 使用支持向量机(SVM)来获取一个句子背后最有可能的含义,并在其中加上情感元素。 总体上来说,我们使用了 22 种模型(22 个 SVM) 并且在一篇文档中,每一个单词我们都会加以分析。因此如果你有一篇 500 字的文档,那么基于 SVM,会进行十万次的比较。
PythonRepustate 几乎完全就是一个 Python 商店。我们使用 Django 来实现 API 和网站。因此(目前)为了保持代码一致,同时使用 Python 来实现阿拉伯语情感引擎是合情合理的。只是做原型和实现的话,Python 是很好的选择。它的表达能力很强悍,第三方类库等等也很好。如果你就是为了Web服务,Python 很完美。但是当你进行低级别的计算,大量依赖于哈希表(Python 里的字典类型)做比较的时候,一切都变慢了。我们每秒能处理大约两到三个阿拉伯文档,但是这太慢了。比较下来,我们的英语情感引擎每秒能处理大约五百份文档。
瓶颈因此我们开启了 Python 分析器,开始调查是什么地方用了那么长时间。还记得我前面说过我们有 22 个 SVM 并且每个单词都需要经过处理吗?好吧,这些都是线性处理的,非并行处理。所以我们的第一反应是把线性处理改成 map/reduce 那样的操作。简单来说:Python 不太适合用作 map/reduce。当你需要并发的时候,Python 算上好用。在 2013 Python 大会上(译者:PyCon 2013),Guido 谈到了 Tulip,他的这个新项目正在弥补 Python 这方面的不足,不过得过段一段时间才能推出,但是如果已经有了更好用的东西,我们为什么还要等呢?
选 Go 语言,还是回家算了?我在Mozilla的朋友告诉我,Mozilla 内部正在将他们大量的基础日志架构切换到 Go 语言上,部分原因是因为强大的 [编程语言是如何工作(解释型 vs 编译型, 动态语言 vs 静态语言)有一点理解的话,会说,“切,当然 Go 语言会更快”。是的,我们也可以用 Java 把所有的东西重写一遍,也能看到类似更快的改善,但那不是 Go 语言胜出的原因。你用 Go 写的代码好像就是对的。我搞不清楚到底是怎么回事,但是一旦代码被编译了(编译速度很快),你就会觉得这代码能工作(不只是跑起来不会错,而且甚至逻辑上也是对的)。我知道,这听上去不太靠谱,但是确实如此。这和 Python 在冗余(或非冗余)方面非常类似,它把函数作为第一目标,因此函数编程会很容易想明白。而且当然,go 线程和通道让你的生活更容易,你可以得到静态类型带来的性能大提升,还能更精细的控制内存分配,而你却不必为此在语言表达力上付出太多的代价。
希望能早点知道的事情(Tips & Tricks)除去所有这些赞美之词以后,有时你真的需要在处理 Go 代码的时候,相对于 Python,改变一下思维方式。因此这是我在迁移代码时记录的笔记清单 —— 只是在我把 Python 代码转换到 Go 时从我脑子里随机冒出来的点子:
是不是值得?值得,一百万倍的值得。速度的提升太多了,以致很难舍弃。同时,我认为, Go 是目前趋势所在,因此在招新员工的时候,我认为把 Go 当作 Repustate 技术积累的重要一环会很有帮助。 原文链接: repustate blog 翻译: 伯乐在线 - 伯乐在线读者投稿译文链接: http://blog.jobbole.com/42908/ |