我开发了一个框架,供我们组织中的几个团队使用。在此框架之上开发的那些“模块”可以表现得完全不同,但它们都非常消耗资源,即使有些比其他的更多。他们都在输入中接收数据,分析和/或转换它,然后进一步发送。
我们计划购买新硬件,我的老板让我根据模块定义和实施基准测试,以便比较我们得到的不同报价。
我的想法是简单地以一组精心挑选的数据作为输入按顺序启动每个模块。
你有什么建议吗?对这个简单的程序有何评论?
我开发了一个框架,供我们组织中的几个团队使用。在此框架之上开发的那些“模块”可以表现得完全不同,但它们都非常消耗资源,即使有些比其他的更多。他们都在输入中接收数据,分析和/或转换它,然后进一步发送。
我们计划购买新硬件,我的老板让我根据模块定义和实施基准测试,以便比较我们得到的不同报价。
我的想法是简单地以一组精心挑选的数据作为输入按顺序启动每个模块。
你有什么建议吗?对这个简单的程序有何评论?
你的问题很广泛,所以很遗憾我的回答也不会很具体。
首先,基准测试很难。不要低估产生有意义的、可重复的、高度可信的结果所需的努力。
第二,你的绩效目标是什么?是吞吐量(每秒的事务或操作)吗?是延迟(执行交易所需的时间)吗?你关心平均表现吗?我关心最坏情况下的性能吗?你关心绝对最坏的情况还是我关心 90%、95% 或其他百分位数获得足够的性能?
根据您的目标,您应该设计基准来衡量该目标。因此,如果您对吞吐量感兴趣,您可能希望以规定的速率将消息/事务/输入发送到您的系统,并查看系统是否跟上。
如果您对延迟感兴趣,您将发送消息/事务/输入并测量处理每一个需要多长时间。
如果您对最坏情况下的性能感兴趣,您将向系统添加负载,直到您认为“现实”(或系统设计说它应该支持的任何内容)。
其次,您没有说这些模块是否会受 CPU 限制、I/O 限制、它们是否可以利用多个 CPU/内核等。当您尝试评估不同的硬件解决方案时,您可能会发现您的应用程序会受益更多来自出色的 I/O 子系统与大量 CPU。
第三,最好的基准(也是最难的)是将实际负载放入系统中。这意味着,您记录生产环境中的数据,并通过这些数据放置新的硬件解决方案。完成这项工作比听起来要难,通常,这意味着在系统中添加各种测量点以查看其行为(如果您还没有)修改现有系统以添加记录/播放功能,修改播放以不同的速率运行,并获得一个真实的(即类似于生产)环境进行测试。
最有意义的基准是衡量您的代码在日常使用中的表现。这显然会为您提供最真实的数字。
选择几个现实生活中的数据集,并让它们通过您的组织每天使用的相同流程。为了获得额外的荣誉,请与使用您的框架的人交谈,并要求他们提供一些“最佳情况”、“正常”和“最坏情况”数据。如果存在隐私问题,请匿名数据,但尽量不要更改任何可能影响性能的内容。
请记住,您是在对两组硬件进行基准测试和比较,而不是您的框架。将所有软件视为黑匣子,简单地衡量硬件性能。
最后,考虑保存数据集并使用它们来类似地评估您对软件所做的任何后续更改。
如果您的系统应该能够同时处理所有调用的多个客户端,那么您的基准测试应该反映这一点。请注意,有些电话不能很好地配合使用。例如,让 25 个线程同时发布相同位的信息可能会导致服务器端锁定,从而扭曲您的结果。
从具体细节的角度来看,我使用 Perl 及其Benchmark 模块来收集我关心的信息。
如果您要比较不同的硬件,那么衡量每笔交易的成本可以很好地比较硬件与性能之间的权衡。一种配置可能会为您提供最佳性能,但成本太高。较便宜的配置可能会为您提供足够的性能。
模拟负载的“最坏情况”或“高峰时间”非常重要。使用“典型”卷进行测试也很重要。获得良好的服务器利用率是一种平衡行为,它不会花费太多,它可以提供所需的性能。
跨硬件配置的测试很快就会变得昂贵。另一个可行的选择是首先测量您拥有的配置,然后使用模型在虚拟系统中模拟该行为。
如果可以,请尝试记录用户(或进程)对您的框架所做的一些操作,最好使用真实系统的克隆。这为您提供了最真实的数据。需要考虑的事项:
为 1+2 创建前十名并以此为基础。
也就是说:如果您用新硬件替换旧硬件,您可以预期自您购买第一套以来每年的执行速度大约提高 10%(如果系统在其他方面相当相同)。
如果您有专门的系统,数字可能会完全不同,但通常情况下,新硬件不会有太大变化。例如,向数据库添加有用的索引可以将查询的运行时间从两小时减少到两秒。硬件永远不会给你那个。
在我看来,在基准测试软件方面有两种基准。首先是微基准,当您尝试单独评估一段代码或系统如何处理狭义定义的工作负载时。比较两种用 Java 编写的排序算法。比较两个 Web 浏览器各自执行某些 DOM 操作的速度。其次,当您尝试在实际工作负载下评估软件系统时,有系统基准测试(我刚刚命名)。比较我在 Google Compute Engine 和 Amazon AWS 上运行的基于 Python 的后端。
在处理 Java 之类的东西时,请记住,VM 需要先预热,然后才能为您提供真实的性能。如果使用time
命令测量时间,将包括 JVM 启动时间。您几乎总是希望忽略启动时间或单独跟踪它。
微基准测试
在第一次运行期间,CPU 缓存中会充满必要的数据。磁盘缓存也是如此。在随后的几次运行中,VM 继续预热,这意味着 JIT 会编译它认为有助于编译的内容。您想忽略这些运行并在之后开始测量。
进行大量测量并计算一些统计数据。平均值、中位数、标准差,绘制图表。看看它,看看它有多大的变化。可能影响结果的因素包括 VM 中的 GC 暂停、CPU 上的频率缩放、其他一些进程可能会启动一些后台任务(如病毒扫描)、操作系统可能会决定将进程移动到不同的 CPU 内核上,如果你有 NUMA架构,结果会更加显着。
在微基准测试的情况下,所有这些都是一个问题。在开始之前杀死你可以杀死的进程。使用可以为您完成部分工作的基准测试库。像https://github.com/google/caliper之类的。
系统基准测试
如果在实际工作负载下对系统进行基准测试,这些细节并不真正让您感兴趣,您的问题“只是”知道什么是实际工作负载、如何生成它以及要收集哪些数据。如果您可以检测生产系统并在那里收集数据,那总是最好的。您通常可以这样做,因为您正在测量最终用户特征(网页渲染了多长时间),并且这些特征是 I/O 绑定的,因此收集数据的代码不会减慢系统速度。(页面需要通过网络传送给用户,我们在这个过程中是否也记录了一些数字也没有关系)。
请注意分析和基准测试之间的区别。基准测试可以为您提供做某事所花费的绝对时间,而分析可以为您提供与其他需要做的事情相比所花费的相对时间。这是因为分析器运行大量检测程序(常用技术是每隔几百毫秒停止世界并保存堆栈跟踪)并且检测会显着减慢一切。