性能测试工具的 Coordinated Omission 问题

作者:唐刘

很早之前就看过 Gil 大神的一篇文章《Your Load Generator Is Probably Lying To You - Take The Red Pill And Find Out Why》,里面提到了性能测试工具 coordinated omission 的问题,但当时并没有怎么在意。这几天有人在我们自己的性能测试工具 go-ycsbhttps://github.com/pingcap/go-ycsb/issues/26)上面问了这个问题,我才陡然发现,原来我们也有。

什么是 coordinated omission

首先来说说什么是 coordinated omission。对于绝大多数 benchmark 工具来说,通常都是这样的模型——启动多个线程,每个线程依次的发送 request,接受 response,然后继续下一次的发送。我们记录的 latency 通常就是 response time - request time。这个看起来很 make sense,但实际是有问题的。

一个简单的例子,当我们去 KFC 买炸鸡,然后我们排在了一个队伍后面,前面有 3 个人,开始 2 个人都好快,30 秒搞定,然后第三个墨迹了半天,花了 5 分钟,然后到我了,30 秒搞定。对于我来说,我绝对不会认为我的 latency 是 30 秒,而是会算上排队的时间 2 x 30 + 300,加上服务时间 30 秒,所以我的总的时间耗时是 390 秒。这里不知道大家看到了区别了没有,就是市面上大多数的性能测试工具,其实用的是服务时间,但并没有算上等待时间。

再来看一个例子,假设我们需要性能测试工具按照 10 ops/sec 的频繁发送请求,也就是希望每 100 ms 发送一个。前面 9 个请求,每个都是 50 us 就返回了,但第 10 个请求持续了 1 s,而后面的又是 50 us。可以明显地看到,在 1 s 那里,系统出现了卡顿,但这时候其实只有 1 个请求发上去,并没有很好地对系统进行测试。

YCSB

对于第一个排队的例子,为了更好的计算 latency,YCSB 引入了一个 intended time 的概念,即记录下操作实际的排队时间。它使用了一个 local thread 变量,在 throttle 的时候,记录:

private void throttleNanos(long startTimeNanos) {
 //throttle the operations
 if (_targetOpsPerMs > 0)
    {
 // delay until next tick
 long deadline = startTimeNanos + _opsdone*_targetOpsTickNs;
        sleepUntil(deadline);
        _measurements.setIntendedStartTimeNs(deadline);
    }
}

然后每次操作的时候,使用 intended time 计算排队时间:

public Status read(String table, String key, Set<String> fields,
                 Map<String, ByteIterator> result) {
 try (final TraceScope span = tracer.newScope(scopeStringRead)) {
 long ist = measurements.getIntendedtartTimeNs();
 long st = System.nanoTime();
        Status res = db.read(table, key, fields, result);
 long en = System.nanoTime();
        measure("READ", res, ist, st, en);
        measurements.reportStatus("READ", res);
 return res;
    }
}

需要注意,只有 YCSB 开启了 target,intended time 才有作用。

我当初在看 YCSB 代码的时候,一直没搞明白为什么会有两种时间,而且也不知道 intended time 到底是什么,后来重新回顾了 coordinated omission 才清楚。也就是说 YCSB 通过 intended time 来计算排队时间。

但 YCSB 还是没解决上面说的第二个问题,如果系统真的出现了卡主,测试客户端仍然会跟着卡主,因为是同步发送请求的。在网上搜索了一下,看到了一篇 Paper《Coordinated Omission in NoSQL Database Benchmarking》,里面提到了将同步改成异步的方式,也就是说,每次的任务是一个 Future,首先根据 target 按照频率发 Future 就行,至于这个 Future 什么时候完成,后面再说。而且因为是异步的,所以并不会卡主后面的请求。

Go YCSB

那么具体到 go-ycsb,我们如何解决这个问题呢?我现在唯一能想到的就是利用 Go 的 goroutine,按照一定的频率去生成 goroutine,执行测试。当然 Go 自身也会有调度的开销,这里也需要排除。如果要测试的服务出现了卡顿,就会导致大量的 goroutine 没法释放,最终 OOM。虽然这样子看起来比较残暴,但这才是符合预期的。

这个只是一个想法,具体还没做。一个原因是不同于其他语言,Go 的 goroutine 其实天生就能开很多,所以通常我都是上千并发进行测试的,假设我们有 1000 个并发,按照 1 ms 一次的频率,其实也就等同于每个 goroutine 依次发送了。当然,有总比没有好,如果你对这块感兴趣,欢迎给我们提交 PR,或者给我发邮件详细讨论 tl@pingcap.com。

原文:性能测试工具的 Coordinated Omission 问题

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

BlackPearl 的 ServiceObject 开发部署

K2“BlackPearl”提供一个平台,用于管理和利用现有的跨越任何数量的业务系统的业务信息,以降低成本。它考虑到决策的制定,线路的排定以及报告,并根据360...

1959
来自专栏大数据人工智能

ZStack--工作流引擎

在IaaS软件中的任务通常有很长的执行路径,一个错误可能发生在任意一个给定的步骤。为了保持系统的完整性,一个IaaS软件必须提供一套机制用于回滚先前的操作步骤。...

4684
来自专栏FreeBuf

美国邮政服务网站漏洞可暴露6000万用户数据,现已修复

美国邮政服务系统刚刚修复了一个严重的网站漏洞,该漏洞使得拥有usps.com帐户的任何人都可查看和修改约6000万用户的账户详情。

1163
来自专栏全华班

基于PHP爬虫的博客小程序

小程序后端是基于 Wext-server-thinkphp3.2 实现的数据爬虫,使用 ThinkPHP3.2 框架开发。Wext-server-thinkph...

2741
来自专栏更流畅、简洁的软件开发方式

论程序的成长—— 你写的代码有生命力吗?

做了五年多的程序员了,回过头来看了看以前发的一些帖子,颇有一番感想。 我最得意的就是对数据访问的处理方法(我的数据访问层),倒不是说他有多么的强大、多么的完善,...

2046
来自专栏Java学习网

测试是浪费时间,我的程序肯定没问题

测试是浪费时间,我的程序肯定没问题 尽管关于测试驱动开发(TDD)的书和文章有成百上千之多,仍然有很多人从未感受过测试的强大力量。 之所以不愿意去写测试程序不...

2555
来自专栏北京马哥教育

为什么Python Web流行度不如PHP?

引用 @Rio 的看法:我觉得 Python 不会像 PHP 那样流行,根本原因在于部署的难易程度。 PHP 从语言层面上讲几乎是一无是处,具体实现的质量也乏善...

44312
来自专栏JavaEdge

Java并发编程实战系列11之性能与可伸缩性Performance and Scalability

线程可以充分发挥系统的处理能力,提高资源利用率。同时现有的线程可以提升系统响应性。 但是在安全性与极限性能上,我们首先需要保证的是安全性。 11.1 对性能的...

3645
来自专栏CDN及云技术分享

我是怎么一步步用go找出压测性能瓶颈

笔者要在线上服务器load日志并且重放来测一些机器性能指标。模拟机器资源比较少,相对的被模拟的线上机器日志量大,假设线上单机qps有1w,那么5台机器组成的集群...

1.7K35
来自专栏性能与架构

数据库数据切分

垂直切分 将数据库想象成由很多个一大块一大块的“数据块”(表)组成,垂直地将这些“数据块”切开,然后把它们分散到多台数据库主机上面 ? 优点 (1)数据库的拆分...

3635

扫码关注云+社区