使用 Rally 在 Heat gates 上¶
Heat gate 允许为每个特定的补丁使用 Rally 进行性能测试。此功能可用于检查补丁的性能回归,并检测常见场景中的浮动错误。
如何为特定补丁运行 Rally¶
如上所述,Heat 允许将 Rally 场景作为特定补丁的 gate 任务执行。可以通过在 review 上发布带有文本 check experimental 的评论来完成。它将运行一系列任务,其中一个任务的名称为 gate-rally-dsvm-fakevirt-heat。
将要执行的场景列表在文件 heat-fakevirt.yaml 中呈现。此文件的默认版本可在此处找到:https://github.com/openstack/heat/blob/2025.2/rally-scenarios/heat-fakevirt.yaml
显然,只有在可以与一些其他性能数据进行比较时,性能分析才有意义。因此,可以使用两种不同的方法:
将代码的一部分与一些自定义更改进行比较(参见 检查性能或如何检测回归)
比较两个不同的代码部分(参见 比较输出 API 性能)
使用 Rally 的示例¶
之前强调了两种主要的在 Heat 中使用 Rally job 的方法。本文档的这部分将描述相应的示例。
但是需要注意的是,还有许多其他方法可以使用 Rally job 进行 Heat 性能测试。例如,此 job 可以定期启动(每周两次)用于随机补丁,并且这些结果可以相互比较。这可以了解 Heat 是否存在任何性能回归。
检查性能或如何检测回归¶
使用 Rally 的最简单方法是执行现有的场景。一个示例在补丁 https://review.opendev.org/#/c/279450/ 中呈现。在此补丁中,执行了 Rally 中已存在的场景 HeatStacks.create_and_delete_stack。在执行此场景期间,Rally 会创建 Heat stack,然后在创建 stack 后删除它。所有现有场景都可以在这里找到:https://github.com/openstack/rally-openstack/blob/2025.2/rally_openstack/scenarios/heat/stacks.py
提到的场景使用 Heat 模板作为任务的参数。应为参数 template_path 提及模板路径。它可以是 Rally 存储库中呈现的 Heat 模板之一 (https://github.com/openstack/rally-openstack/tree/2025.2/samples/tasks/scenarios/heat/templates) 或新的模板,就像在提到的补丁中所做的那样。新添加的模板应放置在 rally-scenarios/extra/ 目录中。
也可以为每个 Rally 任务指定其他字段,例如 sla 或 context。有关其他配置设置的更多信息,请访问链接 https://rally.readthedocs.io/en/2025.2/plugins/#rally-plugins 提到的补丁是为确认 Heat 模板验证过程的缓存机制而提出的(参见 https://specs.openstack.org/openstack/heat-specs/specs/2025.2/constraint-validation-cache.html)。因此,它包含 OS::Heat::TestResource 资源中的一些更改,这可以展示上述缓存功能改进。
最初,测试是在当前的 devstack 安装上运行的,在该安装上禁用了缓存(例如,Patch Set 7)。获得的结果如下
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
38.223 |
48.085 |
42.971 |
100.0% |
10 |
heat.delete_stack |
11.755 |
18.155 |
14.085 |
100.0% |
10 |
total |
50.188 |
65.361 |
57.057 |
100.0% |
10 |
在下一个补丁集中(Patch Set 8),通过在提交消息中添加 Depends-On 引用来更新。它允许使用启用缓存的 devstack 执行相同的测试 (https://review.opendev.org/#/c/279400/)。此情况的结果是
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
11.863 |
16.074 |
14.174 |
100.0% |
10 |
heat.delete_stack |
9.144 |
11.663 |
10.595 |
100.0% |
10 |
total |
21.557 |
27.18 |
24.77 |
100.0% |
10 |
将首次和第二次执行中 create_stack 操作的平均值进行比较表明,启用缓存后,create_stack 的速度提高了 3 倍。这是 create_stack 操作的显著改进。需要注意的是,在描述的测试中,每个约束验证请求的延迟为 0.3 秒,如 TestResource 的 constraint_prop_secs 属性中所指定。这可能比实际延迟时间长,但它可以确认缓存正常工作。
这种方法也可以用于检测回归。在这种情况下,工作流程可以表示为以下步骤列表:
将现有或新任务添加到任务列表 (
heat-fakevirt.yaml)。等待本次执行的结果。
上传带有更改(新功能)的补丁集,然后再次启动相同的测试。
比较性能结果。
比较输出 API 性能¶
使用 Rally job 的另一个示例是在 Heat 存储库中编写自定义 Rally 场景。review 上有一个示例:https://review.opendev.org/#/c/270225/
它类似于第一个示例,但需要更多的 Rally 特定编码。 heat-fakevirt.yaml 中的新任务使用 Rally 存储库中未定义的场景
CustomHeatBenchmark.create_stack_and_show_output_new
CustomHeatBenchmark.create_stack_and_show_output_old
CustomHeatBenchmark.create_stack_and_list_output_new
CustomHeatBenchmark.create_stack_and_list_output_old
所有这些场景都定义在同一个补丁中,并放置在 rally-scenarios/plugins/ 目录中。
这些场景和任务的目的是演示新旧 API 调用的差异。Heat 客户端有两个命令用于操作 stack 输出:heat output-list 和 heat output-show <output-id>。 之前没有特殊的 API 调用来从服务器获取此信息,并且此数据是从整个 Heat Stack 对象获得的。在实现新的输出 API 后,这发生了变化:https://specs.openstack.org/openstack/heat-specs/specs/2025.2/api-calls-for-output.html
如上述规范所述,可以通过向 Heat API 发出特殊请求来获取输出。根据这些更改,Heat 客户端中的代码已更新为在可用时使用新的 API。
此更改的最初问题是性能问题,可以表述为:使用旧方法执行命令 heat output-show <output-id> 需要先解析 Heat Stack 中的所有输出,然后才能获取用户指定的单个输出。
对于 heat output-list,也是如此,它需要解析所有输出才能仅提供输出键的列表,而无需解析值。
带有后缀 *_new 的场景使用新的输出 API。这些场景尚未在 Rally 中呈现,因为它是新的 API。带有后缀 *_old 的另两个场景基于获取输出的旧方法。此代码已被新的 API 部分替换,因此无法在新的 devstack 上使用它。因此,此自定义代码被编写为两个自定义场景。
所有这些场景都已添加到任务列表中并同时执行。执行结果如下
create_stack_and_show_output_old¶
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
13.559 |
14.298 |
13.899 |
100.0% |
5 |
heat.show_output_old |
5.214 |
5.297 |
5.252 |
100.0% |
5 |
heat.delete_stack |
5.445 |
6.962 |
6.008 |
100.0% |
5 |
total |
24.243 |
26.146 |
25.159 |
100.0% |
5 |
create_stack_and_show_output_new¶
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
13.719 |
14.286 |
13.935 |
100.0% |
5 |
heat.show_output_new |
0.699 |
0.835 |
0.762 |
100.0% |
5 |
heat.delete_stack |
5.398 |
6.457 |
5.636 |
100.0% |
5 |
total |
19.873 |
21.21 |
20.334 |
100.0% |
5 |
使用旧方法的执行 output-show 的平均值显然高于新 API。这是因为新的 API 仅解析指定的单个输出。
对于 output-list 也是如此
create_stack_and_list_output_old¶
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
13.861 |
14.573 |
14.141 |
100.0% |
5 |
heat.list_output_old |
5.247 |
5.339 |
5.281 |
100.0% |
5 |
heat.delete_stack |
6.727 |
6.845 |
6.776 |
100.0% |
5 |
total |
25.886 |
26.696 |
26.199 |
100.0% |
5 |
create_stack_and_list_output_new¶
行动 |
最小值 (秒) |
最大值 (秒) |
平均值 (秒) |
成功 |
计数 |
heat.create_stack |
13.902 |
21.117 |
16.729 |
100.0% |
5 |
heat.list_output_new |
0.147 |
0.363 |
0.213 |
100.0% |
5 |
heat.delete_stack |
6.616 |
8.202 |
7.022 |
100.0% |
5 |
total |
20.838 |
27.908 |
23.964 |
100.0% |
5 |
这也是预期的,因为获取输出名称列表不需要解析值,就像在新的 API 中所做的那样。
所有上述结果清楚地显示了性能变化,并允许确认新的方法有效。