当我们谈性能的时候,我们实际上在谈什么?

本报道根据2015年QCon上海大会第 二天早上Gil Tene的主题演讲内容整理而成。Gil Tene是Azul Systems公司的联合创始人兼CTO,在过去的25年一直从事虚拟机和运行时技术的开发,兴趣主要是研究系统响应和延迟行为。Gil经常在全球范围的 技术大会上发表演讲,他还是JavaOne明星讲师。他作为主要作者提出了C4(Continuously Concurrent Compacting Collector)垃圾收集算法,该算法也是Azul的响应式Java平台的基础。他擅长Java虚拟化、弹性内存、各种托管运行时等技术,是著名的 Java和JVM专家,过去也从事过操作系统、网络交换机、防火墙等系统的设计与构建。本次QCon上他带来的演讲主题为《Pragmatic Performance》,分享他如何以实用主义的眼光去看待“性能”这件事。

今天的分享并不是要告诉你们有关数据如何测量、有关如何调优的技巧。我在多年从业过程中犯下了非常多的错误,并且有幸从其中的一些错误中学到了新的东西。这些是我今天想要跟大家分享的,我希望大家能够反思自己对“性能”这个东西的理解,反思我们面对“问题”时的思考方式。

“实用”一词,是相对“理论”而言的。要解释“实用”和“理论”之间的区别,最简单的例子就是看屏幕上的这辆跑车。如果你问这样的问题:

“这辆车能跑多快?”

那么你在问的就是它的“理论速度”。你得到的答案可能是189迈/秒,这个速度完全取决于汽车发动机的极限转速、汽车的外型设计等自身因素。

如果你再问另一个问题:

“这辆跑车和一辆电动自行车相比,哪个更快?”

这也是一个有关“理论速度”的问题。而从“实用”的角度应该提出的问题是:

“在周五上午9点的北京四环路上,这辆跑车和一辆电动自行车相比,哪个更快?”

或者是:

“在不出任何交通事故的前提下,这辆跑车能在周五晚上9点的北京四环路上跑多快?”

今天我们做软件的,也经常会问这样类似的问题。比如:

“这个系统/这个工具能够达到每秒多少次查询?”

这就是个太过于简化的“理论问题”。这一个理论问题的背后,隐藏着无数个可能的“实用”问题,它们各自有各自的边界,或者前提条件。在进入这个问题 本身之前,我们务必需要仔细思考有关“这个问题本身”的一些重要问题,比如:我是否需要针对每一个具体问题进行回答并提供正确的答案?是不是可以只回答简 单的那些问题?是否一定要在下一个星期就提供成万上亿个答案?

在比较系统的性能时,要避免把苹果和橘子放在一起比较。比如,系统A的理论性能是每秒处理X个请求,但无法满足部分场景的需求;系统B的理论性能是 每秒处理0.9X个请求,并且能够满足所有场景的需求。这时我们不能说,“系统B更慢,但更可靠”。这种比较是没有意义的。真正有意义的比较是获取系统A 在满足所有需求的情况下的真实性能,并将其与B在同等条件下达成的性能进行比较。

我们说到系统的性能,经常使用下面这样的一些指标:

  • 每秒可以进行多少次执行
  • 延时,或者是响应时间
  • 宕机率
  • 系统宕机之后到恢复到正常状态所用的恢复时间

此类的指标可以有非常多,而且会互相影响。比如在一个场景下你需要系统能够在宕机后1小时内恢复,后来需求改变到需要在1分钟内恢复,我们如果要评 估修改之后的系统,则不能仅仅看它的恢复时间是不是达到1分钟了,还得看其他指标——每秒执行次数、延时、宕机率——是不是仍然维持在之前的状态。

下面举例说明。比如我们对系统有如下要求:无论在多么忙碌的场景下,都要99.9%的请求在20毫秒内返回。那么,如果该系统处理1次请求需耗时100微秒——相当于每秒1000次处理的能力,这样的系统是否能够满足我们的要求?

答案仅仅是“有这个可能”。想象一下,如果1毫秒内进入了50次请求,会造成怎样的结果?

上图是我们一个线上系统的真实数据。横轴是时间,跨度为1天,刻度为1秒;纵轴代表“这一秒的第一个毫秒内进入的请求数”。蓝色的部分是记录的数值,红色的横线是根据系统的处理能力画出的理论最大处理能力。可以看到在不少时间下,蓝色的峰值都超过了红线。

我们然后当然是用“排队”的方式来处理这些峰值请求。但是当我们用到队列的时候,一定要搞清楚一个问题,那就是我们测量的“响应时间”是不是包含了 那些排队的时间。经常发生的情况是,我们测量的可能是“服务处理时间”,而并非真正的“请求响应时间”。就好像你去星巴克买咖啡,服务生平均制作一杯咖啡 的时间就是“服务处理时间”,而“请求响应时间”则是从你开始站在等待买咖啡的队伍末尾开始计算的。实际上我们在请求数频繁大于处理能力的高峰期时去看真 实的延时数据,往往是这样的:

我们总是太快的开始测量。我们一开始的确能拿到一些测量数据,但到了生产环境下,我们往往会为系统的实际表现大吃一惊。

所以在“测量性能”之前我们应该做些什么呢?一个是要明确需求。一切需要进行性能测试的系统至少应该是正确的,即,功能上正确,符合用户对可用性的要求,等等。如果系统本身有错误,那么性能测试的结果无论如何都是无效的。另一个就是要认识到环境的限制、环境的边界。

接下来我想谈论的话题跟垃圾回收(GC)有关。一种通用的说法是GC的使用会影响程序的性能,所有需要性能的地方还是推荐用C/C++/Objective-C。但我今天想请大家从“实用主义”的角度思考性能这个问题。

看看这三个交通工具。宇宙飞船和电动自行车,哪个速度更快?按照理论速度进行比较,答案毋庸置疑。

但我再问:哪一个交通工具能够让我在15分钟内从我家移动到我的上班地点?

或者:就我需要的速度而言,哪一个交通工具是我现在能用上,或者最晚在6个月之内能够用上的?

说GC影响程序的性能,其实主要还是考虑到“浪费资源”这一层。而这种思路其实要追溯到计算机发展阶段的早期。我也经历过那个时代,那是30年 前,256KB的存储被我看作是宝贝一样。如果让那时候的我看到今天的iPhone,我恐怕会把它当作宝山一样看待,但更大的感觉可能是“气愤”。为什 么?这样一台小巧的、多核的、具有大量存储空间、有如此分辨率和色彩的屏幕的大宝贝,是被用来做什么呢?打电话。听音乐。开玩笑吧,你们用这样珍贵的资源 来做“听音乐”这种无聊的事情?

这是两种完全不同的观念。30年前,计算资源被视为珍贵,因此以“节省使用”为正道。而今天,计算资源被视为白菜,因此以“浪费使用”为正道。事实上,正因为我们把计算资源看成白菜,硬件才能有今天这样快速的发展。

所以就今天的程序而言,什么才是“更高的性能”?那并不是最节省使用计算资源的软件,而是最浪费计算资源、却最节省时间资源的软件。所以,尽情的浪费那些计算资源吧!

Advertisements
此条目发表在未分类分类目录。将固定链接加入收藏夹。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s