TPS 的定义:
In the context of blockchains, transactions per second (TPS) refers to the number of transactions that a network is capable of processing each second.
上面的定义很好理解:整个区块链网络作为一个整体,一秒内所能处理的交易量。问题在如何评估 “处理的交易量”?
-
方式一:“处理” 等于 “上链”,所以
TPS = 已上链的交易量 / 块的时间间隔
TPS = 已上链的交易量 / 块的时间间隔 = SUM([block[i].transactions for i in start..=end]) / (block[end].timestamp - block[start].timestamp)
这种理解方式不全面。因为上链只是区块链处理一个交易的最后一个步骤。压测时观测链上数据可以发现,ckb 链的相邻块的交易数量抖动剧烈,不平滑。
虽然短期内交易数量剧烈抖动,但拉长评估周期求平均呢?拉长评估周期后,交易的生命周期缩小成点,此时再求平均,好像也是个办法。
这种方式站在一个全局的视角。
-
方式二:“处理” 覆盖一个交易的整个生命周期,包括进入交易池、同步交易到整个网络、打包、同步块到整个网络,一共四个阶段。
tps-bench 采用这种覆盖得更全面的理解方式,把 RPC
send_transaction
开始的时间点视作生命周期的起始,包含该交易的块上链且同步全网视作生命周期的结束(TODO: 补一张图)。这种方式站在交易操作者的视角,可能需要关心出块间隔、初始准备的交易数量等变量。
上述两种理解方式分别对应着两种压测方式:
-
方式一:狂发交易。截断链的前面部分和后面部分,
TPS = 已上链的交易量 / 块的时间间隔
。 -
方式二:初始时操作者拥有
N
个 UTXO。操作者自己给自己来回转账这N
个 UTXO,交易的频率f
可以换算为tps
。假设操作者能持续稳定地每隔t
时长做一次转账,则tps = 1s / t
,然后我们只要找到一个稳定的最小t
值即可知道最终tps = 1s / t_min
。
按理来说,这两种方式的最终结果应该很相近。做一下实验吧。
fn can_archive(tps: usize) -> bool {
}
# Use bisection to find the best tps
fn bisect_best_tps() -> usize {
let mut max_tps = 1000;
let mut min_tps = 1;
loop {
if max_tps == min_tps {
return max_tps;
}
let target_tps = (max_tps + min_tps) / 2;
if can_archive(target_tps) {
min_tps = target_tps
} else {
max_tps = target_tps
}
}
}