不是语言之争---Go vs Erlang

由于 云巴 系统对高并发、低延迟的需求,咱们对各个语言、平台作了不少的调研比较工做。这天然就包括致力于开发高并发应用的 Go 和 Erlang。正则表达式

并发

Go 对高并发的支持经过 goroutine 实现。goroutine 能够理解为轻量级的 线程(thread)。同一个 Go 应用建立的 goroutine 共享地址空间。shell

Erlang 的高并发经过轻量级 进程(process)实现,每个进程都有独立的状态记录。后端

另外,使用 goroutine 要注意,goroutine 运行完毕后,占用的内存放回内存池备用,不会释放。服务器

对于每个任务都须要有独立状态的场景,Erlang 的 process 更有优点。并发

抢占式调度

Erlang 的任务调度器有一个 reduction budget 的概念。进程的任何操做都会形成预算消耗,包括 函数调用、调用 BIF、进程堆垃圾回收、ETS 读写、发消息(目标邮箱堆积的消息越多,消耗越大)。Erlang 的 正则表达式库 也被作了修改以支持 reductions。因此若是进程在长时间执行正则表达式匹配,也同样会消耗 reductions,也会被抢占。app

Go 以前的调度器只在 syscall 发生时调度,优化后能够在任何函数调用时调度。可是要注意,若是在 goroutine 里写一个死循环,Go 的调度器不能有效抢占,同一个调度器的 其余 goroutine 会被挂起。框架

垃圾回收

像 Java 同样,Go 的垃圾回收是全局的,这意味着一旦垃圾回收被触发,全部的 goroutine 都会被暂停,形成一段时间的业务延迟。函数

Erlang 的垃圾回收是 进程 级别的,每个进程都有本身独立的垃圾回收器,一个进程的垃圾回收被触发,不会形成其余进程被挂起。相对来讲带来的业务延迟小。高并发

错误处理

Erlang 的每个进程都有 进程 ID (PID),同时也能够给进程注册名字,也就是说每个进程都有独立的身份,能够有效的监控每个进程的状态。进程异常退出时,能够捕捉到退出事件,并重启进程(参见 otp 的 supervisor/worker)。单元测试

Go 的 goroutine 没有身份识别,goroutine 的状态没办法监控。

动态反射

Erlang 动态语言的特色,使它自然支持 REPL,另外 Erlang 支持 remote shell,咱们能够在 Erlang 运行时,链接到 remote shell 与任何一个进程交互。这些特性对一个须要长期运行的复杂系统的维护带来了极大的便利。开发阶段也能有一些便利。

Go 是静态语言,不支持 REPL。

静态编译

Erlang 是动态语言,有全部动态语言的全部缺点:

  1. 运行速度慢
  2. 不能作早期错误检查,须要依赖全覆盖单元测试
  3. 代码规模大了,给编写带来困扰

Erlang 如今也引入了 spec,对函数的参数返回值在编译时作类型检查,可是跟静态语言比起来效果差的很远。

不过正是由于是动态语言,Erlang 实现了运行时代码替换,这个特性对一个须要长时间运行的工业级产品,是一个很是重要的功能。

Go 是静态语言,运行速度快,编译时作严格的类型检查,能够避免不少隐患。

框架

Erlang 的 OTP 框架支持服务器端开发常见的几种模式(applications, supervisors, wokers),方便代码的组织。

Go 暂时没看到相似的框架。

第三方库支持

Go 是一个相对比较新的语言,虽然说如今不少项目都开始支持 Go,但不少第三方库的成熟度暂时不如 Erlang。

总结

对于要求低延迟、高并发的后端服务,咱们近期仍是采用 Erlang 为主。但使用 Erlang 的过程当中,Erlang 缺少静态检查的手段,也是一个很麻烦的问题,目前的作法是要求你们都使用 IntelliJ IDEA 编写代码,能够经过 IDE 提早发现部分语言问题。

同时咱们会持续关注 Go 的发展。

关于做者:
weibo: @Tiger_张虎, 云巴 (yunba.io) 创始人,yunba.io 云后端服务。 JPush 创始人,原CTO。 Oracle VM 创始团队成员。
原文:http://zhang.hu/go-vs-erlang/

相关文章
相关标签/搜索