本文来讲讲OPA
的测试(test
)、性能分析(profile
)和(benchmark
)
掌握他们,对于保证策略代码的质量和决策效率有很大的帮助
OPA
的测试很简单。
所有test_
前缀的的规则(rule
)都是测试。
Tips: 虽然是测试,但其本质上其仍是规则,仍然可以被查询。 另外建议文件名遵循
_test.rego
后缀加以区分
这里拿quick-start
的测试例子来看下:
package example_rbac_test
import data.example_rbac
test_not_allow {
not example_rbac.allow with input as {}
}
test_allow {
example_rbac.allow with input as {
"action": {
"operation": "read",
"resource": "widgets",
},
"subject": {"user": "inspector-alice"},
}
}
就这样即覆盖了allow
规则的全部测试用例。
注意这里with
起到了数据模拟的作用(data mocking
)
Tips: 函数不可用
with
替换
对应的命令行是:
cd quick-start
opa test . -v
# 输出如下
data.example_rbac_test.test_not_allow: PASS (693.201µs)
data.example_rbac_test.test_allow: PASS (562.02µs)
--------------------------------------------------------------------------------
PASS: 2/2
也可以查看测试覆盖率:
opa test . -c
设定测试覆盖率标准:
opa test . -c --threshold 100
(这里提示下别忘了vscode-opa
支持可视化覆盖率展示哦)
也支持选择测试用例执行:
opa test -r test_allow . -v
cd quick-start
opa eval --profile -d example.rego -d data.json -i input.json -f pretty "data.example_rbac.allow"
true
+------------------------------+---------+
| METRIC | VALUE |
+------------------------------+---------+
| timer_rego_data_parse_ns | 18332 |
| timer_rego_load_files_ns | 5506307 |
| timer_rego_module_compile_ns | 573408 |
| timer_rego_module_parse_ns | 5226456 |
| timer_rego_query_compile_ns | 87390 |
| timer_rego_query_eval_ns | 292198 |
| timer_rego_query_parse_ns | 277932 |
+------------------------------+---------+
+----------+----------+----------+-------------------------+
| TIME | NUM EVAL | NUM REDO | LOCATION |
+----------+----------+----------+-------------------------+
| 54.121µs | 1 | 1 | data.example_rbac.allow |
| 42.776µs | 1 | 2 | example.rego:15 |
| 37.861µs | 1 | 1 | example.rego:9 |
| 35.81µs | 1 | 1 | example.rego:25 |
| 22.469µs | 1 | 1 | example.rego:10 |
| 21.353µs | 2 | 2 | example.rego:16 |
| 16.888µs | 2 | 1 | example.rego:17 |
| 15.923µs | 2 | 1 | example.rego:23 |
| 14.736µs | 1 | 2 | example.rego:22 |
| 8.798µs | 1 | 1 | example.rego:24 |
+----------+----------+----------+-------------------------+
Tips: --profile 还支持结果排序和限制显示条数
--profile-sort
:对性能分析结果排序,默认按total_time_ns => num_eval => num_redo => file => line
排序, 详见profile-sort 文档--profile-limit
:显示几条分析结果,默认 10 条
opa
也支持benchmark
,基本实现了go
的benchmark
的使用方式, 甚至有更详细的结果(毕竟一直标榜性能么)
默认benchmark
会展示内存(--benchmem
)和查询(--metrics
)的基准测试结果
$ opa bench --count 1 -d example.rego -d data.json -i input.json -f pretty "data.example_rbac.allow"
+-------------------------------------------+------------+
| samples | 14162 |
| ns/op | 93655 |
| B/op | 15117 |
| allocs/op | 311 |
| histogram_timer_rego_query_eval_ns_75% | 89900 |
| histogram_timer_rego_query_eval_ns_90% | 112253 |
| histogram_timer_rego_query_eval_ns_95% | 125465 |
| histogram_timer_rego_query_eval_ns_99% | 222404 |
| histogram_timer_rego_query_eval_ns_99.9% | 549291 |
| histogram_timer_rego_query_eval_ns_99.99% | 550611 |
| histogram_timer_rego_query_eval_ns_count | 14162 |
| histogram_timer_rego_query_eval_ns_max | 550611 |
| histogram_timer_rego_query_eval_ns_mean | 76735 |
| histogram_timer_rego_query_eval_ns_median | 68336 |
| histogram_timer_rego_query_eval_ns_min | 38896 |
| histogram_timer_rego_query_eval_ns_stddev | 38828 |
+-------------------------------------------+------------+
当然也集成到了opa test
中
$ opa test -v --bench example.rego example_test.rego data.json
data.example_rbac_test.test_not_allow 15139 74172 ns/op 62044 timer_rego_query_eval_ns/op 14666 B/op 270 allocs/op
data.example_rbac_test.test_allow 10000 102658 ns/op 90779 timer_rego_query_eval_ns/op 17825 B/op 367 allocs/op
--------------------------------------------------------------------------------
PASS: 2/2
而且--format
指定gobench
的话,还支持了benchstat
, 是Go
亲生的,无疑了
opa test -v --bench --count 5 --format gobench example.rego example_test.rego data.json| tee b.txt
BenchmarkDataExampleRbacTestTestNotAllow 15186 87349 ns/op 73644 timer_rego_query_eval_ns/op 14663 B/op 270 allocs/op
BenchmarkDataExampleRbacTestTestAllow 10000 115857 ns/op 101565 timer_rego_query_eval_ns/op 17828 B/op 367 allocs/op
--------------------------------------------------------------------------------
PASS: 2/2
...
benchstat b.txt
name time/op
DataExampleRbacTestTestNotAllow 92.9µs ±40%
DataExampleRbacTestTestAllow 123µs ± 8%
name timer_rego_query_eval_ns/op
DataExampleRbacTestTestNotAllow 79.0k ±41%
DataExampleRbacTestTestAllow 109k ± 9%
name alloc/op
DataExampleRbacTestTestNotAllow 14.7kB ± 0%
DataExampleRbacTestTestAllow 17.8kB ± 0%
name allocs/op
DataExampleRbacTestTestNotAllow 270 ± 0%
DataExampleRbacTestTestAllow 367 ± 0%
基准测试前后对比自然也是支持,如benchstat old.txt new.txt
,就不详述了。
这些工具固然好,高性能还是需要 follow 一些经验法则的
这里引用官方对于性能优化的建议如下(key-takeaways):
policy
)要最大程度地减少迭代和搜索。
profiler
)可帮助确定策略的哪些部分将从提高的性能中受益最大。benchmark tools
)来帮助获取真实世界的时序数据并检测策略性能变化。里边提到的
partial-evaluation
和rule-indexing
是保证OPA
高性能的两个重要特性,感兴趣的同学可以自行查看下。
下一篇,我们来谈谈OPA
的一个重磅功能 - bundle
, 一种将策略及数据进行包组织的方式,也支持丰富的管理restful api
,适合分布式决策服务的构建。
文章首发公众号:newbmiao
推荐阅读:OPA 系列