搜尋儲存在事件日誌中的數據是否非常慢?
Augur 使用事件日誌來儲存不需要在合約上訪問的數據,因為它比合約儲存便宜約 10 倍。但是,我注意到檢索事件日誌(例如,使用
eth_getLogs
)比檢索契約數據花費的時間要長得多。(我知道過濾器可以讓你監聽新的事件日誌,但我特別關心查找舊的事件日誌。)我真的不明白事件記錄是如何在幕後工作的。目前,我們正在索引日誌的一個(或多個)參數,然後
eth_getLogs
用於搜尋索引參數。例如,所有 Augur 交易都由市場 ID 和賬戶記錄和索引。作為初始載入的一部分,我們的 UI 會查找目前賬戶進行的交易。現在這需要大約 10 秒才能完成。該eth_getLogs
請求是非同步發出的,並與其他初始市場載入任務交錯,因此目前並不太煩人。然而,我擔心隨著 Augur 和乙太坊區塊鏈的整體增長,這將如何擴展。我的問題:隨著區塊鏈變大,檢索事件日誌會變得異常緩慢嗎?更具體地說,時間複雜度是
eth_getLogs
多少? (區塊鏈大小是相關變數還是其他什麼?eth_getLogs
對於我正在嘗試做的事情,甚至是正確的 RPC 請求?基本上任何對這個問題的洞察力都值得讚賞!)
我會盡量回答你的問題。我在 cpp-ethereum 和Parity中研究過布隆過濾器。
隨著區塊鏈變大,檢索事件日誌會變得異常緩慢嗎?
不必要。一切都取決於實現、日誌密度(日誌/塊的平均數量)和記憶體級別的數量。
更具體地說,時間複雜度是
eth_getLogs
多少?在最壞的情況下,每個塊都包含與您的查詢匹配的日誌,它是 0(n)。但這種情況很少見。布隆過濾器利用誤報的機率,因此您的過濾器越複雜(它擁有的主題越多),您獲得結果的速度就越快。
eth_getLogs 甚至是我想要做的正確的 RPC 請求嗎?
是的
總而言之,我相信 10 秒的響應時間是由 go-ethereum 中布隆過濾器的次優實現引起的。以下是具有奇偶校驗的基準測試結果:
查找從塊 0 到 986082 的所有日誌,地址為:0x33990122638b9132ca29c723bdf037f1a891a70c(應該返回 1602 個日誌)。
time curl -X POST --data '{"id":8,"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x0","toBlock":"0xf0be2", "address": "0x33990122638b9132ca29c723bdf037f1a891a70c"}]}' -H "Content-Type: application/json" http://127.0.0.1:3030 >> /dev/null
geth 第一個請求:
real 0m17.003s
geth 第二個請求(我假設結果應該在第一個請求之後記憶體)。
real 0m18.023s
奇偶校驗第一個請求(比 geth 快約 24 倍)
real 0m0.770s
奇偶校驗第二個請求(比 geth 快約 30 倍)
real 0m0.668s
當找不到日誌時,Parity 和 geth 之間的差距會大大縮小:
查找塊 0 到 986082 的所有日誌,地址為:0x33990122638b9132ca29c723bdf037f1a891a70d(地址不存在,返回 0 個日誌)。
time curl -X POST --data '{"id":8,"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x0","toBlock":"0xf0be2", "address": "0x33990122638b9132ca29c723bdf037f1a891a70d"}]}' -H "Content-Type: application/json" http://127.0.0.1:3030 >> /dev/null
geth 第一個請求:
real 0m0.022s
geth 第二個請求
real 0m0.021s
奇偶校驗第一個請求(比 geth 慢 4 倍)
real 0m0.080s
奇偶校驗第二個請求(比 geth 慢 1.5 倍)
real 0m0.030s