mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-22 08:58:12 +00:00
docs: clarify decode hot path boundaries
This commit is contained in:
@@ -75,9 +75,11 @@ Real-world Polymarket API latency broken down by request phase:
|
|||||||
|
|
||||||
Run the WS hot-path benchmark locally with `cargo bench --bench ws_hot_path`.
|
Run the WS hot-path benchmark locally with `cargo bench --bench ws_hot_path`.
|
||||||
|
|
||||||
|
**Parsing paths:** `polyfill-rs` keeps two parsing layers on purpose. The allocation-sensitive WS `book` path uses `WsBookUpdateProcessor` in `src/ws_hot_path.rs`, which walks a reusable `simd-json` tape and applies fixed-point book levels directly. The generic stream parser in `src/decode.rs` is an ergonomic compatibility path: it parses through `serde_json::Value` so it can tolerate batches, unknown event types, and mixed message shapes. Likewise, several generic numeric/decimal deserializers in `src/decode.rs` accept string-or-number API fields through `serde_json::Value`; they are not the zero-allocation hot path.
|
||||||
|
|
||||||
**Key Performance Optimizations:**
|
**Key Performance Optimizations:**
|
||||||
|
|
||||||
The 21.4% performance improvement comes from HTTP/2 tuning with 512KB stream windows optimized for 469KB payloads, explicit Polymarket request headers, SIMD-backed parsing for large REST market responses, and opt-in connection prewarming/keep-alive support.
|
The 21.4% performance improvement comes from HTTP/2 tuning with 512KB stream windows optimized for 469KB payloads, explicit Polymarket request headers, SIMD-backed parsing where the client uses the typed fast-response helper for large REST market responses, and opt-in connection prewarming/keep-alive support.
|
||||||
|
|
||||||
### Memory Architecture
|
### Memory Architecture
|
||||||
|
|
||||||
|
|||||||
+39
-7
@@ -1,7 +1,14 @@
|
|||||||
//! Data decoding utilities for Polymarket client
|
//! Data decoding utilities for the Polymarket client.
|
||||||
//!
|
//!
|
||||||
//! This module provides high-performance decoding functions for various
|
//! This module contains the ergonomic decoding layer used for broad API compatibility:
|
||||||
//! data formats used in trading environments.
|
//! tolerant string-or-number deserializers, raw REST response adapters, and generic
|
||||||
|
//! WebSocket message parsing. Some helpers intentionally parse through
|
||||||
|
//! [`serde_json::Value`] to support Polymarket fields that vary between strings,
|
||||||
|
//! numbers, nulls, and mixed event batches.
|
||||||
|
//!
|
||||||
|
//! The zero-allocation WS `book` processing path is separate. Use
|
||||||
|
//! [`crate::ws_hot_path::WsBookUpdateProcessor`] when applying high-throughput book
|
||||||
|
//! messages directly to [`crate::book::OrderBookManager`].
|
||||||
|
|
||||||
use crate::errors::{PolyfillError, Result};
|
use crate::errors::{PolyfillError, Result};
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
@@ -12,12 +19,15 @@ use serde::{Deserialize, Deserializer};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Fast string to number deserializers
|
/// Flexible string-or-number deserializers for inconsistent API fields.
|
||||||
pub mod deserializers {
|
pub mod deserializers {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
/// Deserialize number from string or number
|
/// Deserialize a number from a string or JSON number.
|
||||||
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes by first decoding into
|
||||||
|
/// `serde_json::Value`. It is not intended for allocation-sensitive hot paths.
|
||||||
pub fn number_from_string<'de, T, D>(deserializer: D) -> std::result::Result<T, D::Error>
|
pub fn number_from_string<'de, T, D>(deserializer: D) -> std::result::Result<T, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
@@ -44,7 +54,10 @@ pub mod deserializers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize optional number from string
|
/// Deserialize an optional number from a string, JSON number, or null.
|
||||||
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes by first decoding into
|
||||||
|
/// `serde_json::Value`. It is not intended for allocation-sensitive hot paths.
|
||||||
pub fn optional_number_from_string<'de, T, D>(
|
pub fn optional_number_from_string<'de, T, D>(
|
||||||
deserializer: D,
|
deserializer: D,
|
||||||
) -> std::result::Result<Option<T>, D::Error>
|
) -> std::result::Result<Option<T>, D::Error>
|
||||||
@@ -120,6 +133,9 @@ pub mod deserializers {
|
|||||||
|
|
||||||
/// Deserialize an optional Decimal from string/number/null.
|
/// Deserialize an optional Decimal from string/number/null.
|
||||||
///
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes by first decoding into
|
||||||
|
/// `serde_json::Value`. It is not intended for allocation-sensitive hot paths.
|
||||||
|
///
|
||||||
/// - `null` => `None`
|
/// - `null` => `None`
|
||||||
/// - `""` => `None`
|
/// - `""` => `None`
|
||||||
/// - invalid values => error
|
/// - invalid values => error
|
||||||
@@ -152,6 +168,9 @@ pub mod deserializers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Like `optional_decimal_from_string`, but returns `None` on parse errors.
|
/// Like `optional_decimal_from_string`, but returns `None` on parse errors.
|
||||||
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes by first decoding into
|
||||||
|
/// `serde_json::Value`. It is not intended for allocation-sensitive hot paths.
|
||||||
pub fn optional_decimal_from_string_default_on_error<'de, D>(
|
pub fn optional_decimal_from_string_default_on_error<'de, D>(
|
||||||
deserializer: D,
|
deserializer: D,
|
||||||
) -> std::result::Result<Option<Decimal>, D::Error>
|
) -> std::result::Result<Option<Decimal>, D::Error>
|
||||||
@@ -176,6 +195,10 @@ pub mod deserializers {
|
|||||||
|
|
||||||
/// Deserialize a Decimal from string/number.
|
/// Deserialize a Decimal from string/number.
|
||||||
///
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes through
|
||||||
|
/// `optional_decimal_from_string`. It is not intended for allocation-sensitive
|
||||||
|
/// hot paths.
|
||||||
|
///
|
||||||
/// - `""` => error
|
/// - `""` => error
|
||||||
/// - invalid values => error
|
/// - invalid values => error
|
||||||
pub fn decimal_from_string<'de, D>(deserializer: D) -> std::result::Result<Decimal, D::Error>
|
pub fn decimal_from_string<'de, D>(deserializer: D) -> std::result::Result<Decimal, D::Error>
|
||||||
@@ -188,6 +211,10 @@ pub mod deserializers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize a Decimal from string/number/null, defaulting missing-ish values to zero.
|
/// Deserialize a Decimal from string/number/null, defaulting missing-ish values to zero.
|
||||||
|
///
|
||||||
|
/// This compatibility helper accepts multiple API shapes through
|
||||||
|
/// `optional_decimal_from_string`. It is not intended for allocation-sensitive
|
||||||
|
/// hot paths.
|
||||||
pub fn decimal_from_string_or_zero<'de, D>(
|
pub fn decimal_from_string_or_zero<'de, D>(
|
||||||
deserializer: D,
|
deserializer: D,
|
||||||
) -> std::result::Result<Decimal, D::Error>
|
) -> std::result::Result<Decimal, D::Error>
|
||||||
@@ -455,12 +482,17 @@ impl Decoder<Market> for RawMarketResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WebSocket message parsing (official `event_type` shape).
|
/// Ergonomic WebSocket message parsing (official `event_type` shape).
|
||||||
///
|
///
|
||||||
/// Polymarket WebSocket servers may send either a single JSON object or a batch array.
|
/// Polymarket WebSocket servers may send either a single JSON object or a batch array.
|
||||||
/// This parser is tolerant:
|
/// This parser is tolerant:
|
||||||
/// - Unknown/unsupported `event_type`s are ignored.
|
/// - Unknown/unsupported `event_type`s are ignored.
|
||||||
/// - Invalid entries inside a batch are skipped (do not fail the whole batch).
|
/// - Invalid entries inside a batch are skipped (do not fail the whole batch).
|
||||||
|
///
|
||||||
|
/// This is the compatibility parser for general stream consumers. It parses into
|
||||||
|
/// `serde_json::Value` first so it can inspect event types and skip unknown messages.
|
||||||
|
/// For allocation-sensitive WS `book` updates, use
|
||||||
|
/// [`crate::ws_hot_path::WsBookUpdateProcessor`] instead.
|
||||||
pub fn parse_stream_messages(raw: &str) -> Result<Vec<StreamMessage>> {
|
pub fn parse_stream_messages(raw: &str) -> Result<Vec<StreamMessage>> {
|
||||||
parse_stream_messages_bytes(raw.as_bytes())
|
parse_stream_messages_bytes(raw.as_bytes())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user