20.9 Evaluation: HLL performance cost(2)

接下来稍微介绍GC pause。Go的GC是一个带有短暂pause的并发GC,它在一段非常短的时间内停止程序运行来执行write barrier,之后再恢复应用程序的运行,同时GC也会完成自己的工作。Go的GC也是递增的,就像我们在Lec17中介绍过的一样,每次调用new都会做一些GC的工作。所以每次GC做一些工作的时候,应用程序都会有一些延时,这就是代价。

所以我们做了一些测试,我们找了个应用程序并测试了最大的pause时间。也就是由于GC可能导致应用程序最大的停止时间。

最大的单个pause时间是115微秒,也就是在web server中,因为使用了TCP stack,TCP Connection table中很大一部分需要被标记(注,GC的一部分工作是标记对象),这花费了115微秒。一个HTTP请求最大的pause时间是582微秒,所以当一个请求走到一个机器,最多会有总共582微秒延时来执行这个请求。而超过100微秒的pause发生的非常非常少,只有少于0.3%。

如果你尝试达成某种SLA,其中要求的最长请求处理时间很短,那么582微秒就很严重。但是如果你查看Google论文,The Tail at Scale,其中介绍有关一个请求最长可以有多长处理时间,他们讨论的都是几毫秒或者几十毫秒这个量级。所以Biscuit拥有最大pause时间是582微秒还在预算之内,虽然不理想,但是也不会很夸张。这表明了,Golang的设计人员把GC实现的太好了。并且我们在做Biscuit项目的时候发现,每次我们升级Go runtime,新的runtime都会带一个更好的GC,相应的GC pause时间也会变得更小。

之前在Linux和Biscuit之间的对比并不真正的公平,因为Biscuit和Linux实现的是不同的功能。所以我们做了一个额外的测试,我们写了两个完全相同的内核,一个用C实现,另一个用Golang实现。这两个内核实现了完全相同的东西,并且我们会查看汇编代码以检查区别在哪。可能会有一些区别,因为Golang会做一些安全检查,但是对于基本功能来说,汇编代码是一样的。

以上是有关测试的一部分,通过pipe来回传输一个字节。我们查看内核中有关将一个字节从pipe的一端传到另一端的代码。Go里面是1.2K行代码,C里面是1.8K行代码。这里没有内存分配和GC,所以这里只有语言上的差异。我们还查看了两种实现语言中花费最多时间的10个地方,这样我们才能确保两种语言实现的代码尽可能的接近。

之后我们查看了每秒可以完成的操作数,如你可见Golang要慢15%。如果你查看Golang的Prologue和safety-check,这些指令是C代码所没有的,这些指令占了16%,这与更慢的处理速度匹配的上。所以这里的主要结论是Golang是更慢,但并不是非常夸张的慢,Golang还是非常有竞争力的。并且这与我们早些时候做的Biscuit和Linux对比结果一致。

第6个问题跳过。

Last updated