---
title: "我們如何評測 RPC 效能"
description: "評測數據很容易被引用，也很容易被誤讀。以下說明 Alchemy 的公開 EVM read 評測如何在受控條件下測量延遲、成功率、失敗與逾時。"
---

# 我們如何評測 RPC 效能

<ImageBlock
  src="https://media.alchemy.com/blog/how-we-benchmark-rpc-performance-hero-v2.png"
  alt="Benchmark methodology 主視覺圖"
  width={1024}
  height={480}
  priority
/>

[基準測試數字](https://www.alchemy.com/benchmarks)很容易被引用,也很容易被誤讀。[RPC 效能](https://www.alchemy.com/overviews/rpc-node)尤其如此。一張延遲圖表可能隱藏了好幾個不同的問題:請求從哪裡發出、執行了哪個方法、送出了什麼負載、什麼算成功、失敗如何處理,以及測試的是一次 RPC 呼叫還是完整的應用程式流程。

我們建立了[公開的 EVM 讀取基準測試](https://www.alchemy.com/benchmarks),目的就是要讓這些細節變得可見。目標是在受控、可重複的測試環境下,呈現各家供應商之間的比較結果。

我們的基準測試回答的問題是:在選定的鏈、地區與時間區間內,各家供應商在常見 EVM JSON-RPC 讀取方法上的表現如何比較。

這些是方法層級的基礎設施基準測試:針對每個方法、鏈、供應商與地區,分別執行一套受控的方法論。它們量測的是個別的 RPC 請求,而不是完整的應用程式流程,例如載入錢包投資組合、準備一筆 swap,或是跨多次呼叫輪詢交易狀態。這個區別很重要:方法層級的結果有助於開發者比較供應商的行為,但它們並不是任何正式應用程式的完整模型。

## 什麼是 Alchemy 的公開 EVM 讀取基準測試?

Alchemy 的[公開 EVM 讀取基準測試](https://www.alchemy.com/benchmarks)是一項受控測試,用來量測 RPC 供應商對設定好的 EVM JSON-RPC 讀取請求的回應方式。它會記錄成功回應的延遲(平均值、p50、p95)、成功率,以及失敗請求數量,並依供應商、鏈、方法、地區與時間區間分組呈現。

我們只針對成功回應計算延遲。失敗的嘗試與逾時則另外透過成功率與失敗請求數量追蹤。這樣可以讓基準測試同時聚焦在速度與可靠性上,而不是把兩者混為一談單獨看待。

## 定義與量測規則

以下是本文其餘部分所依據的定義、設定與規則。每一列的內容會在下方章節中進一步說明。

<EmbeddedTable
  table={{
    columns: [
      {
        key: "concept",
        width: 260,
        title: "Concept or rule",
        dataType: "object",
      },
      {
        key: "meaning",
        width: 680,
        title: "What it means",
        dataType: "object",
      },
    ],
    data: [
      {
        concept: { title: "What the benchmark measures", tooltip: "", icon: "" },
        meaning: {
          title:
            "Successful-response latency (average, p50, p95), success rate, and failed-request counts for configured EVM JSON-RPC read requests. Results are grouped by provider, chain, method, region, and time window.",
          tooltip: "",
          icon: "",
        },
        id: 0,
      },
      {
        concept: { title: "JSON-RPC", tooltip: "", icon: "" },
        meaning: {
          title:
            'The standard message format apps use to ask blockchain nodes for data. In plain English, the app sends a structured request like "get this wallet balance" or "return this transaction receipt," and the node sends back a structured answer.',
          tooltip: "",
          icon: "",
        },
        id: 1,
      },
      {
        concept: { title: "Method-level benchmark", tooltip: "", icon: "" },
        meaning: {
          title:
            "A test of one configured RPC request with one payload, such as eth_getBalance, eth_getBlockByNumber, eth_getLogs, or eth_getTransactionReceipt.",
          tooltip: "",
          icon: "",
        },
        id: 2,
      },
      {
        concept: { title: "What is not measured", tooltip: "", icon: "" },
        meaning: {
          title:
            "Full app workflows, write transactions, customer-specific traffic mixes, first-request connection setup, block freshness, every chain, every provider, and every possible payload shape.",
          tooltip: "",
          icon: "",
        },
        id: 3,
      },
      {
        concept: { title: "Request origin", tooltip: "", icon: "" },
        meaning: {
          title:
            "The benchmark runs from controlled AWS ECS regions: US East, US West, EU Central, and AP Southeast. This describes benchmark traffic only, not all Alchemy production traffic.",
          tooltip: "",
          icon: "",
        },
        id: 4,
      },
      {
        concept: { title: "Test frequency", tooltip: "", icon: "" },
        meaning: {
          title: "Common public EVM read methods run approximately every 10 seconds.",
          tooltip: "",
          icon: "",
        },
        id: 5,
      },
      {
        concept: { title: "Success criteria", tooltip: "", icon: "" },
        meaning: {
          title:
            "A request succeeds only if it returns before the 8-second timeout, returns HTTP 2xx, parses as JSON, and does not contain a JSON-RPC error object.",
          tooltip: "",
          icon: "",
        },
        id: 6,
      },
      {
        concept: { title: "Latency calculation", tooltip: "", icon: "" },
        meaning: {
          title:
            "Latency is measured only for successful responses. It is runner-side wall-clock time for the measured JSON-RPC POST request and response over a warmed, reused HTTP connection.",
          tooltip: "",
          icon: "",
        },
        id: 7,
      },
      {
        concept: { title: "Timeout handling", tooltip: "", icon: "" },
        meaning: {
          title:
            "Timeouts count as failures. They are not inserted into latency calculations as 8,000 ms responses.",
          tooltip: "",
          icon: "",
        },
        id: 8,
      },
      {
        concept: { title: "Retries", tooltip: "", icon: "" },
        meaning: {
          title:
            "None. The benchmark makes one attempt. If that attempt fails, the failure is counted.",
          tooltip: "",
          icon: "",
        },
        id: 9,
      },
      {
        concept: { title: "Latency with success rate", tooltip: "", icon: "" },
        meaning: {
          title:
            "Latency shows how quickly valid responses return. Success rate shows how often they return successfully at all.",
          tooltip: "",
          icon: "",
        },
        id: 10,
      },
    ],
  }}
/>

## 基準測試涵蓋哪些範圍?

這項基準測試涵蓋 Ethereum、Optimism、Arbitrum、Base 與 World Chain 主網,公開的供應商清單包括 Alchemy、dRPC、Infura 與 QuickNode。我們選擇這些對象是為了涵蓋廣泛使用的 EVM 主網,以及開發者最常評估的 RPC 供應商,並保留日後擴充範圍的空間。對於某個方法,每家供應商都會收到相同設定的 JSON-RPC 請求。

我們從受控的 AWS ECS 地區執行每項測試:美國東部、美國西部、歐洲中部與亞太東南部。在同一個地區內,每家供應商都是從相同的執行器位置進行測試,因為網路距離會影響延遲。如果我們用維吉尼亞州測試某家供應商,又用新加坡測試另一家,結果反映的就會是地理因素而不是供應商的效能。

每項結果依以下條件分組:

- 供應商
- 鏈
- 方法
- 地區
- 移動時間區間

## 基準測試送出什麼內容給每家供應商?

方法(method)指的是被呼叫的操作,例如 `eth_getBalance` 或 `eth_getLogs`。負載(payload)則是我們送出以執行該方法的完整請求內容,包括其參數。這個區別很重要,因為效能同時取決於兩者:一次低成本的查詢與一次大範圍的掃描,對供應商造成的負載截然不同,而即使是同一個方法,也會因輸入內容不同而有所變化。

對於某個方法,每家供應商都會在標準付費帳號下收到相同設定的 JSON-RPC 負載。這就是公平性的原則:相同的方法、相同的參數、相同的鏈、相同的地區、相同的逾時設定、相同的成功判定標準,任何供應商都沒有特殊待遇。

目前這代表在大多數鏈上有七項設定好的測試,而在 Ethereum 上則有八項:

- `eth_getBalance`:帳戶餘額查詢
- `eth_getBlockByNumber`(`earliest` 區塊):讀取鏈起始處的區塊標頭
- `eth_getBlockByNumber`(`latest` 區塊):讀取鏈頭的區塊標頭
- `eth_getLogs`:1 個區塊範圍
- `eth_getLogs`:10 個區塊範圍
- `eth_getLogs`:100 個區塊範圍
- `eth_getLogs`:1,000 個區塊範圍(僅限 Ethereum)
- `eth_getTransactionReceipt`:單筆交易收據查詢

有些負載會隨著鏈的狀態變動。舉例來說,使用 `latest` 區塊標籤的呼叫,會隨著鏈的推進而改變。其他則使用固定的歷史輸入值:Ethereum 上的 `eth_getLogs` 測試,使用的是針對 LINK 代幣合約設定好的固定歷史區塊範圍。

這樣的組合是刻意設計的:

- 固定輸入值讓部分測試具有可重複性。
- 移動輸入值讓部分測試能反映即時的鏈上狀態。
- 固定的歷史輸入值可能較容易被供應商快取。

RPC 效能可能會因方法、參數、區塊範圍、回應大小、快取行為與鏈上狀態不同而有很大差異。在閱讀基準測試結果時,請聚焦在最接近你自己工作負載的方法與參數上。

## 效能是如何量測的?

我們透過兩項訊號來量測效能,各自回答不同的問題:延遲,即成功回應返回的速度有多快(以平均值、p50 與 p95 呈現);以及成功率,即請求整體成功的頻率有多高(背後有失敗請求數量作為佐證)。

這兩者相關但不同:一次快速的成功回應,並不等同於一次可靠的回應。我們將兩者並列呈現,避免其中一項掩蓋另一項。

## 延遲是如何量測的?

延遲指的是執行器針對一次成功的 JSON-RPC HTTP POST 所量測到的請求與回應時間。計時器在執行器送出請求時開始,在收到回應時停止。如果某家供應商在 120 毫秒內回傳有效回應,該次請求的延遲就是 120 毫秒。

我們使用預熱過、可重複使用的 HTTP 連線。簡單來說,我們並沒有計入開啟新連線所需的初始設定步驟,例如 DNS 查詢、TCP 連線建立,或 TLS 交握。執行器會先預熱連線,然後才在一個共用的 keep-alive 連線上量測 POST 本身。

這樣一來,延遲數字就更接近重複性應用程式流量的情況,因為客戶端通常會重複使用連線。但這也表示,你不應該把這些數字解讀為冷啟動首次請求的延遲。

只有成功的回應會被納入延遲分布。如果請求逾時、回傳 HTTP 錯誤、回傳 JSON-RPC 錯誤物件、解析失敗,或發生網路錯誤,我們會將其計為失敗的嘗試。

逾時不會被當作 8,000 毫秒的緩慢回應處理。我們會將其排除在延遲計算之外,並計入成功率當中,藉此讓延遲專注於回應速度,成功率則專注於可靠性。

## 什麼是成功率?

成功率是指在基準測試規則下,成功返回的請求佔所有嘗試請求的比例:成功請求數除以總嘗試請求數。

一次請求只有在以下條件全部成立時才算成功:

1. 在基準測試的逾時時間內完成。
2. 回傳 HTTP 2xx 狀態碼。
3. 回應內容可解析為 JSON。
4. JSON-RPC 回應中不包含非空值的 `error` 物件。

我們不會用重試來掩蓋失敗的嘗試。每一次嘗試請求只有一次機會。如果失敗,就會被計入。

## 基準測試如何處理逾時?

基準測試執行器最多會等待 8 秒,等待每家供應商回傳有效回應。如果在時限內沒有收到有效回應,我們會將該次嘗試記錄為逾時失敗。

這 8 秒的截止時間是我們測試設定的一部分。它並非由鏈本身決定,也不是供應商內部可能使用的任何逾時設定。

目前所有公開的 EVM 讀取方法都適用這個 8 秒的截止時間。某個特定方法理論上可以設定不同的逾時時間,但目前並沒有任何方法這麼做。

## 什麼算是失敗的請求?

我們會將失敗的嘗試與延遲分開追蹤。如果一次請求發生以下任一情況,就會被計為失敗:

- 回傳非 2xx 的 HTTP 狀態碼,例如 403、429、500、502、503 或 504
- 回傳 JSON-RPC 錯誤物件
- 8 秒後逾時
- 在網路層級失敗,或
- 無法解析為有效的 JSON

速率限制的回應也算作失敗,而且我們從不使用重試把失敗的嘗試轉變成成功的結果。每一次失敗都會降低該供應商的成功率,並累加到該方法、鏈、地區與時間區間的失敗請求數量中。

## 這些指標是如何定義的?

<EmbeddedTable
  table={{
    columns: [
      { key: "metric", width: 200, title: "Metric", dataType: "object" },
      {
        key: "technicalDefinition",
        width: 320,
        title: "Technical definition",
        dataType: "object",
      },
      {
        key: "plainEnglishMeaning",
        width: 280,
        title: "Plain-English meaning",
        dataType: "object",
      },
      {
        key: "importantCaveat",
        width: 280,
        title: "Important caveat",
        dataType: "object",
      },
    ],
    data: [
      {
        metric: { title: "Average latency", tooltip: "", icon: "" },
        technicalDefinition: {
          title:
            "Sum of successful response times divided by count of successful responses.",
          tooltip: "",
          icon: "",
        },
        plainEnglishMeaning: {
          title: "On successful calls, how long did the provider take on average?",
          tooltip: "",
          icon: "",
        },
        importantCaveat: {
          title: "Excludes failures, so it must be read with success rate.",
          tooltip: "",
          icon: "",
        },
        id: 0,
      },
      {
        metric: { title: "p50 latency", tooltip: "", icon: "" },
        technicalDefinition: {
          title:
            "Median latency across successful responses in the same provider, chain, method, region, and window group.",
          tooltip: "",
          icon: "",
        },
        plainEnglishMeaning: {
          title: "The typical successful response time.",
          tooltip: "",
          icon: "",
        },
        importantCaveat: {
          title: "Can hide slower tail behavior.",
          tooltip: "",
          icon: "",
        },
        id: 1,
      },
      {
        metric: { title: "p95 latency", tooltip: "", icon: "" },
        technicalDefinition: {
          title:
            "The latency point where 95% of successful responses were faster and 5% were slower.",
          tooltip: "",
          icon: "",
        },
        plainEnglishMeaning: {
          title: "How slow successful requests get outside the normal case.",
          tooltip: "",
          icon: "",
        },
        importantCaveat: {
          title:
            "Timeouts are not included as 8-second samples; they count as failures.",
          tooltip: "",
          icon: "",
        },
        id: 2,
      },
      {
        metric: { title: "Success rate", tooltip: "", icon: "" },
        technicalDefinition: {
          title: "Successful requests divided by total attempted requests.",
          tooltip: "",
          icon: "",
        },
        plainEnglishMeaning: {
          title: "How often the provider returned successfully under the test rules.",
          tooltip: "",
          icon: "",
        },
        importantCaveat: {
          title: "The reliability companion to latency.",
          tooltip: "",
          icon: "",
        },
        id: 3,
      },
      {
        metric: { title: "Failed requests", tooltip: "", icon: "" },
        technicalDefinition: {
          title: "Count of attempts that did not meet the success criteria.",
          tooltip: "",
          icon: "",
        },
        plainEnglishMeaning: {
          title: "How many requests failed.",
          tooltip: "",
          icon: "",
        },
        importantCaveat: {
          title: "Shown as counts per method; the flip side of success rate.",
          tooltip: "",
          icon: "",
        },
        id: 4,
      },
    ],
  }}
/>

## 為什麼要把延遲與成功率放在一起呈現?

只有在回應真的能夠返回時,快速的回應才有意義。有些供應商在成功的請求上可能顯示出很低的延遲,但同時逾時或失敗的頻率也比較高,因此我們會將延遲與成功率並列呈現:延遲顯示有效回應返回的速度,成功率顯示回應整體返回的頻率。

舉例來說,如果我們送出 1,000 次嘗試,其中 990 次在 8 秒逾時之前成功返回,成功率就是 99%。這 10 次失敗的嘗試不會被計入 p50、p95 或平均延遲,而是會反映在可靠性的失敗數字上。

這樣可以避免兩種誤讀:延遲低但失敗較多的供應商,不應該只憑速度來評判;成功率高但尾端延遲較慢的供應商,也不應該只憑可靠性來評判。

## 為什麼基準測試使用移動時間區間?

基準測試會持續執行。常見的公開 EVM 讀取方法大約每 10 秒執行一次,而我們每 5 分鐘就會根據過去 24 小時的移動時間區間,更新一次[公開基準測試頁面](https://www.alchemy.com/benchmarks)。

在完全正常運作的情況下,一個每 10 秒執行一次的方法,每天會針對每個供應商、方法、網路與地區產生大約 8,640 次嘗試。移動的 24 小時時間區間讓每個公開數字都有足夠的樣本數,可以平滑掉偶發的異常波動,同時維持頁面資訊的即時性。

因此,請把公開頁面上的數字視為一個滾動更新的每日總結,而不是單一次請求、一次性測試,或某個瞬間的快照。

## 基準測試不量測哪些內容?

目前,這項基準測試量測的是受控條件下、單一方法的暖連線讀取效能。它並不量測:

- 多次呼叫組成的使用者流程
- 寫入交易或交易送出
- WebSocket 或訂閱行為
- 特定客戶的請求組合
- 冷啟動首次請求的連線建立
- 每一家供應商、每一條鏈、每一個地區、每一個方法或每一種負載形式
- 你自己的架構、流量水準或部署地理位置的實際行為

正是這個範圍界線,讓這項基準測試變得有用:它告訴你這些數字適用於哪些情況,以及你應該在哪些情況下自行執行符合自身工作負載的測試。

速度與可靠性是相關但不同的問題:

- 速度問的是成功請求返回的速度有多快。
- 可靠性問的是請求整體成功返回的頻率有多高。

我們在設計這項基準測試時,刻意呈現這個區別,而不是把它們壓縮成單一的「最快供應商」這種說法。

## 開發者應該如何使用這些結果?

把[公開基準測試](https://www.alchemy.com/benchmarks)當作評估供應商的起點。以下是一種實用的閱讀方式:

1. 選出最接近你工作負載的鏈與方法。
2. 比較最符合你使用者或基礎設施所在位置的地區。
3. 查看 p95,而不只是平均值或 p50。
4. 將成功率與延遲一併檢視。
5. 如果你的工作負載使用不同的負載內容、更高的並發量、寫入操作、WebSocket,或多次呼叫的流程,在做出決定之前,請先執行符合你自身工作負載的基準測試。

透明的基準測試能幫助你提出更好的問題。它們讓你更容易看清楚測試了什麼、計算了什麼、排除了什麼,以及結果中哪些部分對實際應用程式最為重要。

## 常見問題

### 什麼是 Alchemy 的公開 EVM 讀取基準測試?

這是一項受控測試,用來量測 RPC 供應商如何處理常見的 EVM JSON-RPC 讀取請求。它會記錄成功回應的延遲(平均值、p50、p95)、成功率,以及失敗請求數量,涵蓋選定的供應商、鏈、方法與地區,讓開發者能在相同、可重複的條件下比較供應商,而不是依賴行銷宣傳。

### RPC 延遲是如何量測的?

延遲是執行器針對一次 JSON-RPC POST 及其回應、在預熱過且重複使用的連線上所量測到的實際時間。計時器在請求送出時開始,在收到有效回應時停止。只有成功的回應會被計入,因此延遲反映的是回應速度,而不是連線建立或失敗的情況。

### 什麼算是成功的請求?

一次請求只有在 8 秒逾時時間內返回、回傳 HTTP 2xx 狀態碼、可解析為 JSON,且不包含 JSON-RPC 錯誤物件時,才算成功。其他情況,包括逾時、HTTP 錯誤與速率限制回應,都會被計為失敗的嘗試,並排除在延遲計算之外。

### 基準測試如何處理逾時?

執行器最多會等待 8 秒,等待有效回應返回。如果時限內沒有收到回應,該次嘗試會被記錄為逾時失敗,而不是視為 8,000 毫秒的緩慢回應。逾時會降低成功率,但絕不會拉高延遲數字,藉此讓速度與可靠性維持為各自獨立的量測指標。

### 基準測試會使用重試嗎?

不會。每次量測都是單一次嘗試。如果該次嘗試失敗,失敗就會被計入,而不會透過重試來掩蓋。這樣可以確保成功率如實反映情況,因為重試會掩蓋掉實際應用程式真正會遇到的間歇性失敗。

### 基準測試涵蓋哪些鏈與供應商?

公開的基準測試涵蓋 Ethereum、Optimism、Arbitrum、Base 與 World Chain 主網。供應商清單包括 Alchemy、dRPC、Infura 與 QuickNode。針對某個方法,每家供應商都會從相同的地區,在相同的逾時設定與成功判定規則下,收到相同設定的請求。

### 基準測試測試哪些 RPC 方法?

這項基準測試執行七項設定好的讀取測試,建構自四個 EVM 方法:`eth_getBalance`;`eth_getBlockByNumber`(最早與最新區塊);`eth_getLogs`(1、10 與 100 個區塊範圍);以及 `eth_getTransactionReceipt`。Ethereum 額外加上一項 1,000 個區塊範圍的 `eth_getLogs` 測試,共計八項。每一項都使用固定的負載,以確保各供應商之間的結果具有可比較性。

### 基準測試不量測哪些內容?

它不量測完整的應用程式流程、寫入交易、WebSocket 訂閱、特定客戶的流量組合,或冷連線建立。它也未涵蓋所有的鏈、供應商、地區、方法或負載形式。針對這些情況,請執行符合你自身流量的工作負載專屬基準測試。

### 我該如何解讀 p95 延遲數字?

可以這樣理解 p95:在特定的方法、鏈、地區與時間區間內,95% 的成功回應至少有這麼快。它揭露了平均值會掩蓋的尾端行為。請務必將它與成功率一併檢視,因為只有在回應真的能夠返回時,快速的回應才有意義。
