撰文:PREDA
文章来源:https://scrawny-harp-c48.notion.site/961fd557689340cfa45586ef47f856ef
英文版本:https://medium.com/@devteam_48518/a-survey-of-parallel-evm-9aed9d50aee0
本文的内容和目的
无论是在传统的数据库领域还是在区块链技术中,并行执行模型的设计都较为复杂。 这是因为,在设计过程中,需要综合考虑多个维度,而每个维度的选择都会对系统的整体性能和可扩展性产生深远影响。本文将深入探讨当前最具代表性的几种区块链执行层并行架构,并详细呈现我们针对这些架构在性能和可扩展性方面所做的实验结果。
从一个维度来说,区块链领域一直处在对链的高性能和高可扩展性的持续追求中。即使在多链系统和 Layer2 系统出现后,每个智能合约的执行能力仍受限于单一虚拟机 VM 的能力。随着并行虚拟机(Parallel VM)的出现,这一局限得到了突破。并行虚拟机允许单个智能合约的交易在多个 EVM/VM 上同时执行,从而利用更多的CPU核心来提高性能。
我们认为,在众多支持并行VM的高性能区块链系统中,Sei(V2)、Aptos、Sui、Crystality 和 PREDA 最具代表性,每个系统都具备设计上的独特优势。
在本文开篇,我们展示了第一组实验结果。下图展示了在 128 核的机器上,执行相同的ERC20 智能合约时,Sei、Aptos、Sui、Crystality 和 PREDA 的每秒交易数(TPS)的绝对值。从这组实验结果来看,PREDA 模型在五个并行执行系统的 TPS 和可扩展性比较中占据了显著优势。
其他实验数据和分析,我们将在后文详细展开。
以下,我们将详细说明我们实验中的具体方法和操作:
我们首先比较了五个系统的 TPS 值,即吞吐量。在不同链上进行的 TPS 对比实验中所用的交易量相同。
考虑到不同系统中采用的不同编程语言和底层虚拟机不同,单一的吞吐量比较不能完全说明系统的优劣,我们还进行了相对加速结果即 Speedup Ratio 的比较,即同样数量的交易在多个 VM 相对于在一个 VM 上执行的加速效果。在 Sui、Aptos、Crystality 和 PREDA 中,每个线程都分配了一个专用 CPU core。
所有详细的实验数据,包括绝对 TPS 值和加速比,请参阅完整的实验报告。
下表中展示了实验中所用的数据来源、实施过程和评估方法。
并行执行模型一览
Aptos 和 Sui 两个项目,都衍生于 Meta( 曾名 Facebook)宣告失败的区块链项目 Diem。两个项目均由前 Meta 工程师创立——Aptos 由 Avery Ching 创立,Sui 由 Sam Blackshear 创立。二者随后沿循的技术路线却不尽相同,Aptos 严格遵循为 Diem 开发的原始 Move 编程语言,但 Sui 对 Move 进行了大量修改。
接下来,我们将探讨 Aptos 和 Sui 的并行化模型的差异,分析它们采取的不同方法如何影响性能,并重点介绍它们各自的优势。
Aptos:采用乐观并行化的高性能 Layer 1
Aptos 是一个 Layer 1,通过乐观并行化机制实现智能合约的并行执行,从而提升高性能。具体来说在乐观并行化中,交易被初步假设为无状态冲突并以并行方式执行。执行后,系统会检查冲突,并通过回滚和串行执行方式或通过不同的调度,重新执行冲突交易来解决冲突。这种推测执行方法假设大多数交易不会发生冲突,从而最大化并行执行的优势,同时提供了处理冲突的备用机制。
乐观并行化的优势:(1) 不需要修改程序:无需对现有代码进行更改即可轻松实现。(2) 在冲突只占低到中等百分比的场景下的效率:通过允许许多交易并发进行,并在出现冲突时再处理冲突,最大化吞吐量,在许多现实场景中,冲突相对较少。
Aptos 使用 MOVE 编程语言进行智能合约开发,并在系统实现中使用 Aptos MOVE 虚拟机。
Sui:采用悲观并行化的高性能 Layer 1
Sui 采用了一种悲观并行化策略。在悲观并行化中,系统在执行前会预先检查交易是否可能发生资源争用。程序员需要指定每笔交易需要访问的资源(即状态)。系统对每个接收到的交易进行预检查,以检测潜在冲突。只有不涉及与当前执行中的交易发生资源争用的交易,才会被送至执行引擎进行并行执行。
悲观并行化的优势:(1) 避免回滚:通过在执行前识别并避免冲突,此方法最小化了回滚和重新执行的需求,从而实现更可预测的性能。(2) 在高冲突场景中的效率:在高争用环境中非常有效,确保只有不冲突的交易并行执行,减少冲突解决所带来的开销。
Sui 也使用 MOVE 编程语言,但具有自己的 Sui MOVE 扩展,并在系统实现中使用 Sui MOVE 虚拟机。
Sei:与 Solidity 和 EVM 兼容的乐观并行化
Sei最初推出公链时,其定位是基于 Cosmos SDK 构建的交易型应用链,现在已升级为首个并行化 EVM 链。在并行执行这一层面,Sei 采用了一种类似于 Aptos 模型的方法,我们称之为乐观并行化。
Sei (V2) 所采用的乐观并行,其与众不同之处在于使用 Solidity 编程语言和标准以太坊虚拟机(EVM),确保 EVM 和 Solidity 兼容性。
Crystality 和 PREDA:并行接力执行架构
Crystality 和 PREDA 都支持并行接力执行分布式架构(Parallel Relay-Execution Distributed Architecture)。PREDA 是为多 EVM 区块链架构里的并行化通用智能合约而专门设计。二者的关系是,Crystality 是一种用于并行 EVM/GPU 的编程语言,其基础是 PREDA 模型。从系统的角度来说,PREDA首次在区块链领域,使合约功能的完全并行化成为可能,因此能最大化一组交易的并发性。这确保了所有 EVM 实例的高效利用,从而达到一定硬件配置条件下的最佳性能和可扩展性。
与 Solidity 和 Move 的顺序执行,和Shared Everything的架构设计不同,PREDA 模型首次采用了Shared Nothing架构,以打破并行执行中的状态依赖,并确保不同的 EVM 实例永远不会访问同一片合约状态,从而几乎完全避免了写冲突。
在 PREDA 中,合约函数被分解为多个有序步骤,每个步骤依赖于状态中一个可并行化且无冲突的部分。用户发起的交易首先会被发送到一个持有用户地址状态的 EVM 上。在交易执行过程中,执行流可以通过发出接力交易从一个持有当前管理所需合约状态的 EVM 切换到另一个 EVM的方式,实现数据不动,而执行流根据数据依赖关系在 EVM 之间移动。
五大代表性合约的实验数据
在我们的评估中,我们测试了五个广泛使用的智能合约——ETH TokenTransfer、Voting、Airdrop、CryptoKitties 和 MillionPixel,以及 MyToken (ERC20)。这些合约在包括 Sei、Aptos、Sui、Crystality 和 PREDA 在内的各种区块链系统上执行。我们进行了详细的实验,以比较不同并行执行系统的性能,重点关注每秒交易量 (TPS) 和加速比,这些指标衡量了在多个虚拟机上与各系统单个虚拟机上执行时相对的性能提升。
所有详细的实验数据,包括绝对 TPS 值和加速比,请参阅完整的实验报告。
ETH TokenTransfer 合约:该实验使用了与标准 ERC20 智能合约相同的实际历史 ETH 交易。
Voting 合约:Voting 合约是 PREDA 模型如何简化并行投票算法的绝好例子。它利用 Crystality 和 PREDA 的数据拆分、接力和执行机制,在绝对 TPS 和加速比上均优于乐观(Aptos)和悲观(Sui)并行化方法。原本在 Solidity 中的顺序算法现在允许跨虚拟机并行投票,并将结果从临时数组中聚合。
AirDrop:此合约从一个地址向多个地址触发多次代币或 NFT 转移。它具有一对多的状态更改模式。在这种情况下,Sei、Aptos 或 Sui 中的两个交易不能并行执行。只有通过并行粒度更高的PREDA 模型,能使这些交易能够以流水线模式并行处理。
CryptoKitties:这个合约是以太坊上的一款流行游戏合约,涉及根据父母猫的基因繁殖子代猫。与前述合约不同,这个合约在处理用户发起的交易时需要访问多个地址状态,包括「父猫」、「母猫」和「新生猫」。该合约在从父母基因中计算新生猫的基因时还涉及比前述合约更复杂的计算。
MillionPixel:在以太坊上的这个游戏合约中,用户们要抢先在地图上标记坐标。这个智能合约用于展示 PREDA 模型的灵活性。除了按地址划分合约状态外,程序员还可以定制分区键,例如在这种情况下从地址类型切换为 uint32 类型。
为了方便读者理解上述大量数据,以下重点关注分析两个特别有代表性的合约。
ETH Token转账合约:在回放 ETH 历史交易数据时,五个系统的绝对吞吐量和可扩展性比率均较 ERC20 实验有所下降。这是因为历史交易中重复的地址导致了状态争用(读写冲突或写写冲突),从而阻碍了这些交易在并行 EVM 中的并发执行。
Voting 合约:Sei 合约几乎只能按顺序执行,在运行多个 EVM 时没有速度提升。如果算法没有转变为并行算法,其他系统也会出现类似的结果。对于 Aptos 和 Sui 的并行实现,必须为「proposal」变量的临时结果在不同地址初始化多个资源。此外,并行实现还必须基于投票者的地址提供手动调度,将投票者的交易引导至不同的虚拟机,并访问临时结果以进行并行执行。
由实验结果得到的启发
从实验结果中我们得到了以下启示:
对比乐观与悲观并行方法
Aptos 和 Sui 在不同的特定场景中各有其最佳表现。在 ERC20 转账案例中,Aptos 表现优于 Sui,这是因为 ERC20 转账的每笔交易中使用随机生成的地址,导致冲突非常少。相反,在 ETH 测试案例中,由于回放 ETH 历史交易带来的大量冲突,Sui 的表现优于 Aptos。
Aptos 执行中的时间分析
下表展示了在运行这 2 个合约时 Aptos 的性能分析数据(使用相同的智能合约,但交易数据分别采用的随机生成或历史交易数据)。由于性能分析十分耗时,测试所用的并行虚拟机数量最多限制在 64 个。
Aptos 交易执行包括执行和验证两个步骤,测试数据显示其中大量的交易执行状态被标记为「SUSPEND」(挂起),且这些交易执行耗时很长。「SUSPEND」意味着交易执行暂停,直到其状态依赖关系得到解决才可以恢复执行。对于 64个虚拟机上的随机交易,执行和验证的总次数分别为 102,219 次和 139,426 次。而对于历史交易,这些数字增加到 186,948 次和 667,148 次,交易挂起次数从 66 次增加到 46,913 次。因此,当交易执行中发生大量状态冲突时,回滚成为乐观并行化的沉重负担。
Sui 执行中的时间分析
以下图表展示了 Sui 在 ETH Token 转账合约测试和 Voting 合约测试中的耗时明细。在 Sui 的并行执行引擎中,有三个主要步骤:(1) 排队时间:交易被事务管理器选中之前的等待时间;(2) 任务管理时间:交易被放入 Sui 的 Executing Txns 哈希图或 Pending Txns 哈希图,到它被 Sui 的 Execution Driver 接收之间的时间;(3) 函数执行时间:由 Execution Driver 中的工作线程执行合约函数的时间。
任务管理时间涉Locking和等待两个部分。对比这两个图表可以看出,Voting测试中的任务管理时间占整个执行时间的比例明显比ETH Token转账测试大得多。这是因为在Voting测试中,访问共享对象需要通过Locking和等待来避免冲突,使得任务管理时间比函数执行时间和排队时间多了2到4个数量级。相比之下,在ETH Token转账测试中,由于只使用了Owned Objects,绕过了并发控制,任务管理时间要少得多。
Aptos 和 Sui 的局限性
总结来说,Aptos 采用乐观并行化,即使在存在冲突的情况下也允许并行交易执行。这种基于乐观并发控制(OCC)的方法对以读取为主的工作负载非常有效,这在写入请求稀少的数据库和大数据系统中较为常见。然而,在区块链系统中,由于链上执行涉及的gas 费用,这种方法可能会产生巨大的 Gas 开销。实际上,用户通常将只读请求(例如历史交易或区块查询)发送到像 Etherscan 这样的链下数据库,而写入请求则用于链上执行。在这种情况下,像 Aptos 这样的 OCC 系统将频繁遇到交易「Suspend」(中止)和挂起,从而降低并行虚拟机的整体性能。
相比之下,Sui 采用悲观并行化,严格验证交易之间的状态依赖性,并通过 Locking 机制防止执行过程中的冲突。这种基于悲观并发控制(PCC)的方法更适合计算密集型工作负载,在这种情况下,PCC相关的开销甚至小到忽略不计。但在逻辑简单的操作中,PCC 相关的开销很容易成为性能瓶颈。在现实世界里,许多在区块链系统上执行的交易,如 ERC20 Token 转账、Move Token 转账或 NFT 转账,都涉及相对简单的操作。具体来说,ERC20 代币转账通常涉及从一个地址减去一定金额并将其加到另一个地址。类似地,Move Token 转账或 NFT 转账涉及将一个资源或对象从一个地址移动到另一个地址。即使要考虑所有权验证等额外检查, 这些操作也非常快速。此时,PCC 的相关开销就会成为并行系统性能的限制因素。
为了解决这些挑战,PREDA 提出了一个几乎完全避免 PCC 开销和 OCC 重新执行需求的系统。该方法通过高效地拆分链上状态实现几乎无冲突的并行执行。
Crystality 和 PREDA 的性能表现
在所有合约测试中,Crystality 和 PREDA 的性能数据都显著优于 Sei、Aptos 和 Sui,其中 PREDA 表现尤为突出,因为它以原生二进制模式而非 WASM 进行执行。这种高性能得益于几乎无冲突的并行执行。PREDA 从设计之初就考虑了以下2个关键环节:
定义不同的合约状态范围,系统将依据这个范围进行状态拆分和维护。
要实现交易的执行流从一个虚拟机到另一个虚拟机的切换。
PREDA 的核心在于引入了可编程作用域(Programmable Contract Scopes),将合约状态拆分为不重叠、可并行的细粒度片段;并引入了异步函数接力(Asynchronous Functional Relay),用于描述不同 EVM 之间的执行流切换。
我们来进一步解释这些概念的含义,在 PREDA 中,一个合约函数被分解为多个有序步骤,每个步骤依赖于单一的、可并行的状态片段,且不产生冲突。
举个例子:通常情况下,Token 转账涉及两个步骤:一是提取步骤,即访问Sender的状态并提取指定数量的 Token 的,二是存入步骤,即访问 Recipient 的状态并存入相应数量的 Token。像 Sei、Aptos 和 Sui 等实现的最新并行机制,试图同步执行每个交易中的所有步骤。如果两个交易之间的访问状态是共享的或被更新的,比如当 Sender 或 Recipient 相同时,这两个交易将无法并行执行。
然而,PREDA 采用了一种可拆分且异步的机制,其中交易的各个步骤根据其数据访问依赖性进行分解,使每个步骤能够独立于其他步骤异步执行。对相同状态的访问严格按照原始交易块中确定的顺序进行序列化,并由共识算法保证,即由区块创建者排序。
例如,Token转账交易 Txn 0(将代币从地址状态 A 转移到状态 B)和 Txn 1(从状态 A 转移到状态 C)可以按照顺序两次访问 A(分别用于 Txn 0 和 Txn 1),然后并行访问 B 和 C。
Aptos,Sei 和 PREDA 中并行执行的架构比较
PREDA 和 Crystality 的局限性
尽管 PREDA 和 Crystality 能为区块链系统赋能, 提供显著的性能优势,但它们的局限性也体现在如下方面。
并行 EVM 之间工作负载不均衡
Crystality 的数据拆分和执行流重定向机制可能会导致并行 EVM 在运行时出现负载不均衡的问题。我们在用 MyToken 合约重放历史 ETH Token转账交易时观察到了这一问题。
为了评估负载分布情况,我们统计了每个 EVM 上执行的交易数量,包括原始交易和接力交易,然后计算了这些数量的极差和标准差。结果显示,在 64 个 EVM 上执行的交易数量极差与 2 个 EVM 上的范围相当,这意味着在某些EVM地址存在热点问题(即历史交易集中发生在一部分地址上)。对 ETH 数据集的进一步调查发现,每一个热点地址涉及高达 4000 多笔交易。这里必须指出的是,据我们了解,Aptos 和 Sui 在这种情况下,也无法做并行化执行。
我们的测试数据表明,随着 EVM 数量的增加,标准差有所降低,这意味着增加更多的 EVM 有助于缓解负载不平衡问题。
为了解决区块链上的热点问题,一个可行的解决方案是使用多个地址而不是单个地址来发送或接收代币。如果负载不均衡是由于几个非热点地址映射到同一虚拟机造成的,那么分片(Sharding)区块链中的现有方法,例如数据迁移,可能会有所帮助。
程序重写
PREDA 和 Crystality 的另一个显著的局限性是,开发者需要使用 directives 重写智能合约。如果有一种工具可以自动将 Solidity、Move 或 Rust 编写的现有智能合约翻译为等效的 Crystality 智能合约,将大大优化开发者的体验。从前人经验看来,也并不难实现,已经有一些研究探索了不同语言之间的翻译,例如从 Solidity 到 Move 和从 Python 到 Solidity。
自然语言处理的技术进步,大大增强了自动代码生成的潜力。这些进展结合基于规则和模式的编译器翻译技术(如用于大数据的 SQL 到 MapReduce 翻译和用于深度学习的计算图到矩阵计算的翻译)完全可以为开发自动化的智能合约翻译工具, 提供助力。
结论
Sei、Aptos、Sui 与 Crystality/PREDA 之间的性能对比突显了区块链并行化领域的不断演变。Aptos(与 Sei)和 Sui 分别展示了乐观并行化和悲观并行化机制的潜力,各自在不同场景下展现了优势。然而,Crystality 和 PREDA 显著的性能提升表明,更先进的并行化模型可能是解锁更高层级的可扩展性和效率的关键。
为了总结我们对区块链领域三种主要并行化方法的探索和观察,我们整理汇总了一张表格。如果您想从这篇文章中获得一份Takeaway,那就是本表格中的内容。