显示软件包…
1 个稳定版本
2.0.0 | 2021 年 4 月 4 日 |
---|---|
0.0.0 |
|
#5 在 #tetcore 中
378 每月下载次数
在 42 个软件包中使用(直接使用 32 个)
1MB
21K SLoC
Tetcore 运行时基准测试框架
此软件包包含一组可用于基准测试和衡量您为 Tetcore 运行时开发的 FABRIC 贵族(noble)的实用工具。
概述
Tetcore 的 FABRIC 框架允许您为您的区块链开发自定义逻辑,这些逻辑可以包含在您的运行时中。这种灵活性对于帮助您设计复杂和交互式的贵族至关重要,但如果没有为可调用的贵族分配准确的权重,您的区块链可能会遭受恶意行为者的拒绝服务(DoS)攻击。
Tetcore 运行时基准测试框架是一个工具,您可以使用它通过基准测试运行时中不同函数所需的计算资源来减轻对您的区块链网络的 DoS 攻击,例如外联(extrinsics),on_initialize
,verify_unsigned
等...
基准测试系统的基本理念是:如果您的节点可以预先知道执行一个外联需要多长时间,它就可以安全地根据其可用资源决定是否包含或排除该外联。通过这样做,它可以保持区块生产和导入过程的顺畅。
为了实现这一点,我们需要通过以下方式模拟运行时中每个函数的运行时间:
- 创建自定义基准测试逻辑,以执行函数的特定代码路径。
- 在 Wasm 执行环境中执行基准测试,在特定的硬件上,使用自定义运行时配置等...
- 在可能影响基准测试结果的可能值范围内执行基准测试(称为“组件”)。
- 在每个点多次执行基准测试,以隔离和去除异常值。
- 使用基准测试的结果创建函数在其组件上的线性模型。
有了这个线性模型,我们能够预先估计执行某些逻辑需要多长时间,从而在运行时不实际消耗任何显著资源的情况下做出明智的决定。
请注意,我们假设所有外联都具有线性复杂度,这就是为什么我们总能将它们拟合到线性模型中。二次或更高复杂度的函数通常被认为是危险的,因为这些函数的权重可能会随着运行时状态或输入的复杂性而爆炸性增长。
基准测试框架包含以下工具
- 一组宏(例如
benchmarks!
、add_benchmark!
等),使编写、测试和添加运行时基准变得容易。 - 一组线性回归分析函数,用于处理基准数据。
- 一个CLI扩展,使在您的节点上执行基准测试变得容易。
在编译节点时,端到端基准测试管道默认是禁用的。如果您想运行基准测试,您需要通过使用Rust功能标志 runtime-benchmarks
来启用它。更多详情见下文。
权重
Tetcore使用称为“权重”的通用单位来表示计算资源。它定义10^12权重为基准测试所使用的物理机器上的1秒计算时间。这意味着函数的权重可能会根据用于基准测试运行时函数的特定硬件而变化。
通过模拟每个运行时函数的预期权重,区块链能够计算出在特定时间段内能够执行多少交易或系统级函数。通常,区块链的限制因素是网络的固定区块生产时间。
在FABRIC中,每个可调度函数必须有一个 #[weight]
注释,该注释是一个可以返回该函数在最坏情况下的预期权重的函数,给定其输入。此基准测试框架将生成一个自动为您生成这些公式的文件,您可以将这些公式用于您的代码。
编写基准测试
编写运行时基准测试与编写您代码的单元测试非常相似。它需要精心设计以执行您的代码中的特定逻辑路径。在测试中,您希望检查各种成功和失败条件,但在基准测试中,您特别关注最 计算密集型 的路径,即“最坏情况”。
这意味着如果存在某些存储项或运行时状态可能会影响函数的复杂性,例如在 for
循环中触发更多迭代,为了获得准确的结果,您必须设置您的基准测试以触发此操作。
可能会有多个路径您的函数可以走,而且不清楚哪个是最重的。在这种情况下,您应该为每个场景创建一个基准测试!您可能会发现您的代码中存在复杂性可能根据用户输入而变得无界的路径。这可能是一个提示,说明您应该强制执行用户如何使用您的代码的合理边界。例如:限制向量的元素数量,限制 for
循环的迭代次数等...
端到端基准测试的示例可以在 Tetcore 提供的 代码 中找到,而关于如何使用 benchmarks!
宏的具体细节可以在 其文档 中找到。
测试基准测试
您可以使用为您的代码单元测试创建的相同测试运行时来测试您的基准测试。通过在 benchmarks!
宏中创建您的基准测试,它将自动为您生成测试函数。
fn test_benchmark_[benchmark_name]<T>::() -> Result<(), &'static str>
只需将这些函数添加到单元测试中,并确保函数的结果为Ok(())
。
注意: 如果您的测试运行时和生产运行时配置不同,测试基准和实际运行时可能会得到不同的结果。
一般来说,返回Ok(())
的基准是您需要检查的,因为这表示执行的外部程序已成功完成。然而,您可以选择在基准测试中包含一个verify
块,该块可以额外验证任何最终条件,例如运行时的最终状态。
这些额外的verify
块不会影响您最终基准测试过程的结果。
要运行测试,您需要启用runtime-benchmarks
功能标志。这也可能意味着您需要进入您的节点二进制文件夹。例如,使用Tetcore存储库,您将这样测试Balances的基准
cargo test -p noble-balances --features runtime-benchmarks
注意:Tetcore使用虚拟工作区,不允许您使用功能标志进行编译。
error: --features is not allowed in the root of a virtual workspace`
要解决这个问题,请导航到节点(
cd bin/node/cli
)或noble(cd fabric/noble
)的文件夹,并在那里运行命令。
添加基准
与每个noble一起包含的基准不会自动添加到您的节点中。要实际执行这些基准,您需要实现fabric_benchmarking::Benchmark
特质。您可以在包含的Tetcore节点中查看如何实现的示例。
假设您的节点上已经设置了一些基准,您只需要添加另一个add_benchmark!
宏实例
/// configuration for running benchmarks
/// | name of your noble's crate (as imported)
/// v v
add_benchmark!(params, batches, noble_balances, Balances);
/// ^ ^
/// where all benchmark results are saved |
/// the `struct` created for your noble by `construct_runtime!`
完成此操作后,您需要使用runtime-benchmarks
功能标志编译您的节点二进制文件
cd bin/node/cli
cargo build --release --features runtime-benchmarks
运行基准
最后,一旦您有了启用基准的节点二进制文件,您需要执行您的各种基准测试。
您可以通过运行以下命令来获取可用的基准列表
./target/release/tetcore benchmark --chain dev --noble "*" --extrinsic "*" --repeat 0
然后您可以按如下方式运行基准
./target/release/tetcore benchmark \
--chain dev \ # Configurable Chain Spec
--execution=wasm \ # Always test with Wasm
--wasm-execution=compiled \ # Always used `wasm-time`
--noble noble_balances \ # Select the noble
--extrinsic transfer \ # Select the extrinsic
--steps 50 \ # Number of samples across component ranges
--repeat 20 \ # Number of times we repeat a benchmark
--output <path> \ # Output benchmark results into a folder or file
这将输出一个文件noble_name.rs
,该文件实现了您应该在noble中包含的WeightInfo
特质。每个区块链都应生成自己的基准文件,其中包含其自定义实现的WeightInfo
特质。这意味着您可以在保持特定配置和要求的同时使用这些模块化的Tetcore nobles。
基准测试CLI使用Handlebars模板来格式化最终输出文件。您可以选择传递--template
标志,指向可以使用的自定义模板。在模板中,您可以访问基准测试CLI writer中TemplateData
结构提供的所有数据。您可以在此处找到默认模板。
输出生成中包含了一些自定义Handlebars辅助函数
underscore
:在字符串的右边第三个字符添加下划线。主要用于分隔大数字。join
:将字符串数组连接成一个空格分隔的字符串,用于模板。主要用于连接传递给命令行接口的所有参数。
要获取运行基准测试时可用选项的完整列表,请运行
./target/release/tetcore benchmark --help
许可证:Apache-2.0
依赖项
~3–12MB
~134K SLoC