抽象的
以太坊正在通過逐步提高The Blockgas 上限來擴容 L1 緩存。然而,大幅提高 gas 上限(例如Dankrad 提出的 100 倍提升方案)會迅速觸及磁盤 I/O 和 CPU 執行速度的瓶頸。預熱和EIP-7928 區塊級訪問控制列表 (BAL)可以消除大部分 I/O 讀取阻塞,將主要瓶頸轉移到執行本身。與此同時,現有客戶端仍然按順序執行交易,從根本上限制了吞吐量。
BAL ( 我們團隊兩年前也探索過這個想法)實現了完美的並行執行,但其性能上限仍不明確。為了解決這個問題,我們構建了一個純執行環境,其中包含:
- 預加載狀態,模擬相關賬戶、存儲槽位和合約代碼通過BAL提示預先解析的環境;
- 預先恢復的發送方,利用大多數客戶端中已實現的並行發送方恢復功能;
- 省略狀態根計算,其成本可以分攤到更大的塊中。
在此環境下,我們使用BAL對每事務並行執行進行了基準測試。結果表明,在現代 16 核商用 PC 上,純執行吞吐量超過10 GigaGas/s ,而當前 Reth 客戶端在相同條件下僅能達到約 1.2 GigaGas/s。這表明,一旦上述瓶頸得到徹底解決,EVM 執行能力可以比當前客戶端基準性能提升一個數量級。
我們今天所處的位置
以太坊在 Fusaka 升級中將 gas 上限從 4500 萬提升至 6000 萬。假設 gas 上限提升 100 倍,則生成的區塊將包含約 4.5 吉 gas。為了將驗證時間控制在三秒以內,驗證者至少需要 1.5 吉 Gas/s 的執行吞吐量。然而, Base 的公開基準測試表明,在普通硬件上運行的現代客戶端最高只能達到約 600 吉 Gas/s。這一限制主要源於順序執行:儘管多核 CPU 已經可用,但現有客戶端仍然採用串行方式處理交易,導致大多數核心未得到充分利用。
| 發射有效載荷 | Geth MGas/s | Reth MGas/s |
|---|---|---|
| 基礎主網模擬 | 316.4 | 591.6 |
當前性能(~0.6 GGas/s)與 100 倍擴展所需的性能(~1.5 GGas/s)之間的差距仍然很大——這促使我們努力實現完全並行的 EVM 執行。
我們是如何做到的
為了研究BAL帶來的極致並行執行性能,我們構建了一個純執行環境,移除了所有無關的非執行部分,從而能夠測量 BAL 並行性的真正上限。利用 Rust 的無垃圾回收設計、對多線程調度的細粒度控制以及 Reth 的高性能,我們修改了 Reth 客戶端,並使用 revm 作為 EVM 執行引擎進行本次實驗。
純粹執行仿真的簡化
- 整個鏈狀態預先加載到內存中(因為我們可以根據 BAL 的讀取位置進行批量 I/O)。
- 所有交易都已恢復發送方身份(發送方恢復可以事先完全並行化)。
- 執行後不會進行狀態根計算和數據庫提交(這是一個瓶頸,但不是本研究的主要重點)。
工程工作及搭建
- 修改了 Reth 客戶端,使其支持轉儲完整的執行依賴項,包括塊、BAL、最後 256 個塊哈希以及從BAL讀取集提示解析的塊前狀態。
- 為 Revm 添加了一個適配器,用於加載
blockEnv、state和txEnv,併為每個交易創建一個單獨的 EVM 實例。 - 並行粒度 =按事務。
- 硬件:AMD Ryzen 9 5950X(16 核),128 GB 內存。
- 數據集:2000 個主網區塊(
#23600500–23602500)。 - 指標:每秒 Gas 消耗量 = 總 Gas 消耗量 / 純執行模擬時間。
基準測試套件可在此處獲取:
https://github.com/dajuguan/evm-benchmark
結果
我們的評估首先針對revm的順序執行性能進行了校準,然後逐步引入並行執行。並行擴展性分析表明,運行時間最長的交易的延遲是限制整體加速的關鍵路徑。為了緩解這一限制,我們模擬了更高的區塊gas限制,從而顯著提升了BAL的並行性。在16個線程和1G區塊gas限制下,純執行吞吐量達到了約14 GGas/s 。
基線對齊與順序執行
我們首先嚐試復現 Reth 的基準測試結果。在預加載 KZG 設置的情況下,對主網數據進行順序運行,純執行速度達到了 1,212 MGas/s。
這一連續結果將作為我們後續所有實驗的參考點。
並行執行及其關鍵路徑瓶頸
為了評估實際加速效果以及阿姆達爾定律對事務級並行性的影響,我們進行了逐事務並行執行實驗,以量化運行時間最長的事務對可實現加速效果的影響。
詳細結果如下所示(其中“最長交易延遲”是指每個區塊中運行時間最長的交易的總執行時間):
| 線程 | 吞吐量(百萬燃氣/秒) | 最長傳輸延遲 | 總時間 |
|---|---|---|---|
| 1 | 1258 | 6.06秒 | 33.47秒 |
| 2 | 2460 | 6.04秒 | 17.12秒 |
| 4 | 3753 | 6.10秒 | 10.71秒 |
| 8 | 4824 | 6.00秒 | 8.73秒 |
| 16 | 5084 | 6.04秒 | 8.29秒 |
總體而言,擴展性測試結果與阿姆達爾定律高度吻合:雖然吞吐量隨著線程數的增加而提高,但塊執行時間受限於最長事務,在16個線程的情況下,最長事務約佔總執行時間的70%,這使得可實現的加速比上限約為5倍,而非16核機器的理想16倍。這表明,可擴展性取決於每個塊的關鍵路徑,而非原始計算能力。
可以通過降低最長交易的主導地位來緩解這種關鍵路徑限制,例如通過EIP-7825:交易 gas 限制上限或增加區塊 gas 限制——本文探討的方法。
7928 + 巨型模塊 = 大規模並行
由於每個區塊的關鍵路徑限制了併發性,我們嘗試使用更高 gas 費用的“巨型區塊”來提高並行性。為了模擬這種情況,我們並行執行了多個連續主網區塊(即巨型區塊或批次)的交易,並在批次中的所有交易完成後才提交狀態(實驗中為空操作)。這有效地將多個區塊聚合為一個大型執行單元。
超大規模工作負載下的並行性分析
我們首先評估了 50 個代碼塊,模擬了不同線程數下平均代碼塊 gas 消耗量為 1,053 M 的情況。完整結果如下所示:
| 線程 | 吞吐量(百萬燃氣/秒) | 最長傳輸延遲 | 總時間 |
|---|---|---|---|
| 1 | 1,440 | 0.50秒 | 29.26秒 |
| 2 | 2,793 | 0.50秒 | 15.08秒 |
| 4 | 5,167 | 0.52秒 | 8.15秒 |
| 8 | 9,095 | 0.54秒 | 4.63秒 |
| 16 | 14,001 | 0.59秒 | 3.01秒 |
由於區塊尺寸如此之大,運行時間最長的交易不再主導關鍵路徑——在 16 個線程下,它們僅佔總執行時間的不到 20%。吞吐量幾乎與線程數呈線性關係:使用 16 個線程,我們實現了 14 GGas/s 的吞吐量,比順序執行快了大約 10 倍,接近理想的線性擴展。這令人非常鼓舞。在我們的實驗中,唯一剩下的主要關鍵路徑是point_evaluation預編譯,而這部分難以輕易並行化。
不同模塊氣體利用率下的吞吐量
為了評估並行執行如何隨著區塊 gas 使用量的增加而擴展,我們執行了連續區塊批次,同時改變了The Block批次大小(即分組到一個大型區塊中的區塊數量),從而模擬了不同的有效區塊 gas 使用量。
| 線程 | 塊批次大小 | 平均塊狀氣體(M) | 吞吐量(百萬燃氣/秒) |
|---|---|---|---|
| 16 | 1 | 21 | 5,084 |
| 16 | 2 | 42 | 6,641 |
| 16 | 5 | 105 | 8,814 |
| 16 | 10 | 210 | 10,228 |
| 16 | 25 | 526 | 12,152 |
| 16 | 50 | 1,053 | 14,001 |
| 16 | 100 | 2,106 | 14,887 |
| 16 | 200 | 4,212 | 15,298 |
隨著The Block氣使用量的增加,吞吐量持續提升,但並行度的增量提升卻從每增加一倍塊氣所對應的約 30% 下降到約 3%。一旦批處理大小超過約 50 個塊(約 10.53 億塊氣),進一步增加塊氣帶來的吞吐量提升微乎其微。
前景
我們的實驗表明,將EIP-7928 與巨型區塊相結合,能夠顯著提升交易執行的可擴展性,在現代 16 核通用處理器上實現了14 GigaGas/s 的純執行吞吐量。然而,仍有幾個問題尚未解決:
1. 發件人恢復
我們在純執行基準測試中排除了發送方恢復。在我們的實驗中,啟用發送方恢復會使吞吐量降低約 2/3,在巨型塊配置(10.53 億塊 gas)下降至約 5 GigaGas/s。
可能的緩解措施:GPU加速的發送方恢復。
2. 天然氣定價模型
7702 交易的point_evaluation預編譯和發送方恢復功能效率較低,其 gas 消耗效率也較低。在 EIP-7928 時代,可能需要重新評估其 gas 定價機制。
3. 交易 Gas 限額
提高區塊 gas 限制可能需要保留當前的交易 gas 限制上限,以維持高並行性。
4. 加快BAL建設
構建器性能預計將成為主要瓶頸。提高BAL構建效率對於跟上純執行吞吐量至關重要。
5. 優化狀態提交
狀態提交是另一個主要瓶頸。加快狀態根計算速度和優化 trie 樹提交對於維持高吞吐量執行至關重要。
其他作品
我們也探索了不同的任務調度策略,例如,根據 gas 消耗量或 gas 上限對高 gas 交易進行排序以提升優先級,以及簡單的有序列表調度器 (OLS),其中交易保持自然區塊順序,並將每個新交易分配給第一個可用的核心。然而,當應用於主網數據時,對高 gas 交易進行優先級排序僅帶來了微小的性能提升,並未顯著影響整體吞吐量。
不同調度策略下的吞吐量
為了評估對整體吞吐量的影響,我們將優先調度高 gas 交易(按 gas 使用量或 gas 限制)與 OLS 進行了比較。
- 普通塊體上的結果:
| 線程(調度器) | 吞吐量(百萬燃氣/秒) | 最長傳輸延遲 | 總時間 |
|---|---|---|---|
| 2(用氣量) | 2,726 | 5.70秒 | 15.45秒 |
| 2(氣體限制) | 2,728 | 5.68秒 | 15.44秒 |
| 2(OLS) | 2,460 | 6.04秒 | 17.12秒 |
| 4(用氣量) | 4,401 | 6.09秒 | 9.57秒 |
| 4(氣體限制) | 4,321 | 6.18秒 | 9.75秒 |
| 4(OLS) | 3,753 | 6.10秒 | 10.71秒 |
| 8(用氣量) | 5,455 | 6.15秒 | 7.72秒 |
| 8(氣體限制) | 5,426 | 6.13秒 | 7.76秒 |
| 8(OLS) | 4,824 | 6.00秒 | 8.73秒 |
| 16(用氣量) | 5,643 | 6.03秒 | 7.47秒 |
| 16(氣體限制) | 5,531 | 6.05秒 | 7.62秒 |
| 16(OLS) | 5,084 | 6.04秒 | 8.28秒 |
- 平均區塊氣體量為 1053M 的巨型區塊的測試結果:
| 線程(調度器) | 吞吐量(百萬燃氣/秒) | 最長傳輸延遲 | 總時間 |
|---|---|---|---|
| 2(氣體限制) | 2,732 | 0.53秒 | 15.42秒 |
| 2(OLS) | 2,793 | 0.50秒 | 15.08秒 |
| 4(氣體限制) | 5,114 | 0.54秒 | 8.24秒 |
| 4(OLS) | 5,167 | 0.52秒 | 8.15秒 |
| 8(氣體限制) | 9,082 | 0.57秒 | 4.64秒 |
| 8(OLS) | 9,095 | 0.54秒 | 4.63秒 |
| 16(氣體限制) | 14,181 | 0.63秒 | 2.97秒 |
| 16(OLS) | 14,001 | 0.59秒 | 3.01秒 |
Toni 的分析表明,在最壞的情況下,優先處理高 gas 消耗的交易可以比 OLS 算法提升 20% 到 80% 的性能。然而,在實際應用中,使用真實的主網數據(代表平均情況)時,性能提升僅為 10% 左右,而且按 gas 限制、gas 使用量或 OLS 進行調度之間的差異微乎其微。在大型區塊上,OLS 算法的性能幾乎與基於 gas 限制的調度算法完全相同。這些觀察結果表明,交易調度並非主要瓶頸;相反,主網交易的固有分佈才是關鍵路徑。


