Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Solución de problemas de RPC12 min de lectura

Latencia de RPC en Monad: Medición, Cuellos de Botella y Optimización de la Velocidad de Consulta

Aprende a medir la latencia de RPC en Monad, comprende los cuellos de botella únicos de la ejecución paralela y los bloques de menos de un segundo, y optimiza tus consultas para mayor velocidad.

TL;DR

Este artículo explica cómo medir y optimizar la latencia de RPC en Monad. Cubre la arquitectura única de Monad (ejecución paralela, ejecución diferida, bloques de menos de un segundo) y cómo afecta el comportamiento de RPC. Obtendrás un método de medición reproducible usando curl y viem, además de estrategias de optimización como batching, caché y suscripciones WebSocket.

Respuesta directa: ¿Qué determina la latencia de RPC en Monad?

La latencia de RPC en Monad es el tiempo entre enviar una solicitud JSON-RPC y recibir una respuesta. Está dominada por tres factores: la distancia de red al endpoint, la carga del endpoint (especialmente los endpoints públicos compartidos) y el peso del método RPC específico. En Monad, el tiempo de bloque de menos de un segundo y el modelo de ejecución diferida añaden un matiz único: la frescura del encabezado del bloque y la disponibilidad del estado pueden variar según cómo el nodo procesa las transacciones. Para obtener baja latencia, necesitas un endpoint dedicado geográficamente cercano y debes diseñar tus consultas para que sean ligeras y almacenables en caché.

Este artículo es una guía práctica para medir y optimizar la latencia de RPC en Monad. No es un benchmark de proveedores; todos los números que veas en la tabla de resultados están pensados para que los reproduzcas en tu propio entorno. Cubriremos la arquitectura de Monad, un método de medición paso a paso, cuellos de botella comunes y técnicas de optimización.

  • Distancia de red: La distancia física entre tu cliente y el endpoint RPC añade tiempo de ida y vuelta (RTT).
  • Saturación del endpoint: Los endpoints públicos son compartidos; el uso intensivo por parte de otros puede causar colas y limitación de velocidad.
  • Peso del método: eth_getLogs en un rango de bloques amplio es mucho más pesado que eth_chainId.
  • Ejecución diferida de Monad: Los bloques se proponen rápidamente, pero el estado puede no estar disponible inmediatamente para todas las transacciones hasta que la ejecución se pone al día.
  • WebSocket vs. polling: En una cadena rápida, hacer polling de eth_blockNumber cada 400 ms puede perder bloques; las suscripciones son más eficientes.

La arquitectura de Monad y su impacto en RPC

Monad es una Capa 1 compatible con EVM que utiliza ejecución optimista paralela y ejecución diferida para lograr un alto rendimiento (objetivo de diseño de 10,000 TPS) con tiempos de bloque de menos de un segundo (alrededor de 1 segundo o menos). El consenso MonadBFT permite una finalidad rápida. Para los clientes RPC, esto significa que los nuevos bloques llegan con frecuencia y el estado puede actualizarse de manera optimista antes de que todas las transacciones se ejecuten por completo.

La documentación de Monad explica que, aunque los bloques se producen rápidamente, la ejecución de las transacciones puede diferirse. Esto significa que cuando consultas eth_blockNumber, puedes obtener el último encabezado de bloque, pero eth_getBalance o eth_call en ese bloque podrían no reflejar todas las transacciones si la ejecución no ha finalizado. Este es un comportamiento documentado, no un error. Para la mayoría de los casos de uso, el retraso es mínimo, pero para aplicaciones sensibles a la latencia, debes ser consciente de ello.

Otra consecuencia de los bloques de menos de un segundo es que hacer polling de nuevos bloques cada 1 segundo puede perder bloques. Las suscripciones WebSocket (eth_subscribe) son la forma recomendada de obtener newHeads y logs en tiempo real. Los documentos de Monad también señalan que eth_getLogs puede ser costoso si consultas un rango de bloques amplio, por lo que debes paginar por ventana de bloques.

  • La ejecución paralela de Monad permite que múltiples transacciones se procesen simultáneamente, pero las lecturas de estado RPC pueden ver una instantánea consistente.
  • La ejecución diferida significa que el estado de un bloque podría no estar completamente disponible inmediatamente después de que se propone el bloque.
  • Los tiempos de bloque de menos de un segundo hacen que el polling sea ineficiente; usa suscripciones WebSocket para datos en tiempo real.
  • eth_getLogs es un método pesado; siempre limita el rango de bloques y usa paginación.

Método de medición reproducible

Para medir con precisión la latencia de RPC en Monad, necesitas separar la latencia de red del tiempo de procesamiento del servidor. El siguiente método usa curl para una verificación rápida y un script de Node.js con viem para estadísticas más detalladas. Todas las mediciones deben ser ejecutadas por ti; proporcionamos el código y una tabla de resultados para completar.

Suposiciones: Tienes Node.js 18+ instalado y tienes acceso a un endpoint RPC de Monad (público o dedicado). La fecha de prueba es 2026-09-02. Recomendamos ejecutar la prueba desde una máquina que esté geográficamente cerca de tu endpoint objetivo para minimizar el ruido de red. Ejecuta cada prueba varias veces (por ejemplo, 10 iteraciones) y calcula la mediana (p50) y el percentil 95 (p95).

  • Usa curl -w para medir el tiempo total y el desglose (DNS, conexión, TTFB, total).
  • Usa un script de viem para enviar solicitudes secuenciales y concurrentes y medir p50/p95.
  • Registra tus resultados en la tabla a continuación; no compares con benchmarks de proveedores.
curl -s -o /dev/null -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -X POST https://rpc.monad.xyz -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'

# Forma esperada de la salida (los valores variarán):
# DNS: 0.001s
# Connect: 0.020s
# TTFB: 0.050s
# Total: 0.051s

Script de medición en Node.js con viem

El siguiente script usa viem para enviar una serie de solicitudes JSON-RPC y medir la latencia. Prueba eth_chainId (barato), eth_blockNumber (barato), eth_getBalance (moderado) y eth_getBlockByNumber (moderado). Ejecuta cada método secuencial y concurrentemente para simular carga real. El script genera las latencias p50 y p95 en milisegundos.

Para ejecutarlo, guarda el código como measure-monad-latency.mjs y ejecuta con node measure-monad-latency.mjs. Necesitarás instalar viem primero: npm install viem.

import { createPublicClient, http } from 'viem';

const RPC_URL = process.env.RPC_URL || 'https://rpc.monad.xyz';
const client = createPublicClient({ transport: http(RPC_URL) });

const methods = {
  eth_chainId: () => client.getChainId(),
  eth_blockNumber: () => client.getBlockNumber(),
  eth_getBalance: () => client.getBalance({ address: '0x0000000000000000000000000000000000000000' }),
  eth_getBlockByNumber: () => client.getBlock({ blockNumber: 1n }),
};

async function measure(method, iterations = 10) {
  const times = [];
  for (let i = 0; i < iterations; i++) {
    const start = performance.now();
    await method();
    times.push(performance.now() - start);
  }
  times.sort((a, b) => a - b);
  const p50 = times[Math.floor(iterations * 0.5)];
  const p95 = times[Math.floor(iterations * 0.95)];
  return { p50, p95 };
}

async function measureConcurrent(method, iterations = 10) {
  const times = [];
  const start = performance.now();
  await Promise.all(Array.from({ length: iterations }, () => method()));
  times.push(performance.now() - start);
  return { p50: times[0], p95: times[0] }; // simplificado para concurrente
}

console.log('Mediciones secuenciales (ms):');
for (const [name, fn] of Object.entries(methods)) {
  const { p50, p95 } = await measure(fn);
  console.log(`${name}: p50=${p50.toFixed(2)} p95=${p95.toFixed(2)}`);
}

console.log('\nMediciones concurrentes (10 solicitudes paralelas, tiempo total ms):');
for (const [name, fn] of Object.entries(methods)) {
  const { p50 } = await measureConcurrent(fn);
  console.log(`${name}: total=${p50.toFixed(2)}`);
}

// Forma esperada de la salida (los valores variarán):
// Mediciones secuenciales (ms):
// eth_chainId: p50=12.34 p95=15.67
// eth_blockNumber: p50=13.45 p95=16.78
// eth_getBalance: p50=20.11 p95=25.34
// eth_getBlockByNumber: p50=18.22 p95=22.45
//
// Mediciones concurrentes (10 solicitudes paralelas, tiempo total ms):
// eth_chainId: total=45.67
// eth_blockNumber: total=48.90
// eth_getBalance: total=70.12
// eth_getBlockByNumber: total=65.43

Tabla de resultados (medición ejecutada por el lector)

Completa la tabla a continuación con tus propias mediciones. Esto no es un benchmark de proveedores; es un método para que compares endpoints o realices un seguimiento del rendimiento a lo largo del tiempo. Usa la misma URL de RPC y ejecuta el script varias veces para obtener resultados estables.

Al comparar endpoints, asegúrate de ejecutar las pruebas desde la misma máquina y en momentos similares del día para reducir la varianza.

  • Registra la URL del endpoint, la fecha y la hora de la prueba.
  • Ejecuta el script al menos 3 veces y toma la mediana de los valores p50.
  • Anota cualquier limitación de velocidad (HTTP 429) o tiempos de espera que encuentres.
| Método | p50 (ms) | p95 (ms) | Total concurrente (ms) |
|--------|----------|----------|------------------------|
| eth_chainId | | | |
| eth_blockNumber | | | |
| eth_getBalance | | | |
| eth_getBlockByNumber | | | |

(Ejemplo de fila: eth_chainId | 12.3 | 15.6 | 45.7)

Cuellos de botella comunes y cómo solucionarlos

Incluso con un endpoint rápido, puedes encontrar cuellos de botella de latencia. Los más comunes son: usar un endpoint público que está lejos, hacer demasiadas solicitudes (especialmente pesadas) y hacer polling de nuevos bloques en lugar de suscribirte. Aquí hay soluciones específicas.

Primero, elige un endpoint que esté geográficamente cerca de tu aplicación. Si tus usuarios son globales, usa un proveedor con distribución geográfica o un endpoint dedicado. El servicio API de OnFinality ofrece endpoints dedicados con cobertura global, pero debes evaluar según tus propias pruebas.

Segundo, agrupa tus solicitudes JSON-RPC. En lugar de enviar 10 llamadas eth_getBalance separadas, usa el endpoint de lote para enviarlas en una sola solicitud HTTP. Esto reduce los viajes de ida y vuelta y la sobrecarga. Muchos proveedores admiten el agrupamiento; consulta la documentación de tu proveedor.

Tercero, almacena en caché el estado de solo lectura. Si consultas con frecuencia el mismo saldo de cuenta o estado de contrato, almacénalo en caché en el cliente e invalida en nuevos bloques. Esto reduce la carga de RPC y la latencia.

Cuarto, al usar eth_getLogs, especifica siempre un rango de bloques y pagina. Por ejemplo, consulta logs en fragmentos de 1000 bloques. Esto evita que el nodo escanee toda la cadena.

Finalmente, para datos en tiempo real, usa suscripciones WebSocket (eth_subscribe) en lugar de polling. Los bloques de menos de un segundo de Monad significan que hacer polling cada 1 segundo perderá bloques. Consulta nuestra guía de WebSocket RPC de Monad para más detalles.

  • Distancia geográfica: Usa un endpoint distribuido geográficamente o dedicado.
  • Agrupamiento: Combina múltiples solicitudes en una sola llamada HTTP.
  • Caché: Almacena en caché saldos y lecturas de estado en el cliente.
  • Paginación de eth_getLogs: Limita el rango de bloques y usa paginación.
  • Suscripciones WebSocket: Úsalas para newHeads y logs en lugar de polling.

Consideraciones específicas de Monad: Ejecución diferida y frescura del bloque

La ejecución diferida de Monad puede causar una situación donde eth_blockNumber devuelve un bloque que aún no se ha ejecutado por completo. Este es un comportamiento documentado: el encabezado del bloque está disponible inmediatamente, pero las lecturas de estado (eth_getBalance, eth_call) pueden reflejar el estado antes de que algunas transacciones en ese bloque se apliquen. Para la mayoría de las aplicaciones, esto no es un problema porque el retraso es de milisegundos. Sin embargo, si necesitas leer un estado que depende de las últimas transacciones, debes esperar a que el bloque se finalice o usar un método que asegure la ejecución.

La documentación de Monad sugiere usar eth_getBlockByNumber con la etiqueta 'pending' para obtener el último estado, pero esto no siempre es confiable. El enfoque más seguro es usar un endpoint dedicado que esté configurado para esperar la ejecución, o añadir un pequeño retraso (por ejemplo, 100 ms) después de ver un nuevo bloque antes de consultar el estado.

Otra consideración es el tiempo de bloque. Con bloques de menos de un segundo, el método eth_blockNumber devolverá un nuevo valor con mucha frecuencia. Si estás haciendo polling, podrías ser limitado por velocidad. Usa suscripciones WebSocket para recibir eventos newHeads a medida que ocurren, lo cual es más eficiente y de menor latencia.

  • Ejecución diferida: eth_blockNumber puede devolver un bloque cuyo estado aún no está completamente actualizado.
  • Para leer el estado después de un nuevo bloque, espera a que la ejecución se ponga al día o usa un endpoint dedicado.
  • Los bloques de menos de un segundo hacen que el polling sea ineficiente; usa suscripciones.

Compensaciones y limitaciones

Optimizar la latencia a menudo implica compensaciones. Por ejemplo, usar un endpoint dedicado cuesta más que uno público, pero te da un rendimiento consistente. Agrupar solicitudes reduce la latencia pero añade complejidad a tu código. Almacenar en caché el estado reduce la carga de RPC pero puede servir datos obsoletos si no se invalida correctamente.

También hay limitaciones en lo que puedes optimizar. La latencia de red está limitada por la velocidad de la luz; no puedes reducirla más allá de la distancia física. Los endpoints públicos son compartidos, por lo que no puedes controlar la carga de otros usuarios. Y la ejecución diferida de Monad es una característica del protocolo; no puedes desactivarla.

Al medir la latencia, ten en cuenta que tus resultados variarán según el endpoint, la hora del día y las condiciones de red. Siempre ejecuta múltiples pruebas y usa percentiles (p50, p95) en lugar de promedios para obtener una imagen realista.

  • Los endpoints dedicados cuestan más pero ofrecen un rendimiento consistente.
  • El agrupamiento añade complejidad al código pero reduce los viajes de ida y vuelta.
  • El almacenamiento en caché puede servir datos obsoletos si no se invalida en nuevos bloques.
  • La latencia de red es física; no puedes reducirla más allá de la distancia.
  • Los endpoints públicos son compartidos; no puedes controlar la carga de otros usuarios.

Próximos pasos y lecturas adicionales

Ahora que sabes cómo medir y optimizar la latencia de RPC en Monad, puedes aplicar estas técnicas a tus propias aplicaciones. Comienza ejecutando el script de medición contra tu endpoint actual, luego prueba las optimizaciones y mide de nuevo. Deberías ver mejoras en la latencia p95.

Para más orientación sobre RPC de Monad, consulta nuestros otros artículos: Endpoints RPC de Monad (Asistente RPC) para la selección de endpoints, Tiempo de espera y reintentos de RPC de Monad para manejar tiempos de espera, y Límites de velocidad de RPC de Monad y errores 429 para evitar límites de velocidad. También consulta la Guía de WebSocket RPC de Monad para datos en tiempo real.

Si estás construyendo en Monad, también podrías querer explorar la página de red principal de Monad para detalles de red, y el centro de aprendizaje de OnFinality para más tutoriales. Para precios de endpoints dedicados, consulta Precios de RPC.

  • Ejecuta el script de medición contra tu endpoint y registra los resultados.
  • Implementa agrupamiento, almacenamiento en caché y suscripciones WebSocket.
  • Vuelve a medir para ver las mejoras.
  • Explora guías relacionadas sobre tiempos de espera, límites de velocidad y WebSocket.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar