Unnamed repository; edit this file 'description' to name the repository.
perf(transport): switch to `sonic_rs` for parsing (#13690)
| -rw-r--r-- | Cargo.lock | 251 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | helix-dap/Cargo.toml | 2 | ||||
| -rw-r--r-- | helix-dap/src/lib.rs | 14 | ||||
| -rw-r--r-- | helix-dap/src/transport.rs | 8 | ||||
| -rw-r--r-- | helix-lsp/Cargo.toml | 1 | ||||
| -rw-r--r-- | helix-lsp/src/lib.rs | 14 | ||||
| -rw-r--r-- | helix-lsp/src/transport.rs | 10 |
8 files changed, 274 insertions, 27 deletions
@@ -24,6 +24,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.1", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -108,9 +121,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byteorder" @@ -120,9 +133,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cassowary" @@ -398,6 +411,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] +name = "faststr" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baec6a0289d7f1fe5665586ef7340af82e3037207bef60f5785e57569776f0c8" +dependencies = [ + "bytes", + "rkyv", + "serde", + "simdutf8", +] + +[[package]] name = "fern" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1435,6 +1460,7 @@ dependencies = [ "serde", "serde_json", "slotmap", + "sonic-rs", "thiserror", "tokio", "tokio-stream", @@ -1489,6 +1515,7 @@ dependencies = [ "serde", "serde_json", "slotmap", + "sonic-rs", "thiserror", "tokio", "tokio-stream", @@ -1950,10 +1977,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2094,6 +2122,26 @@ dependencies = [ ] [[package]] +name = "munge" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "nucleo" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2240,6 +2288,26 @@ dependencies = [ ] [[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "pulldown-cmark" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2269,6 +2337,15 @@ dependencies = [ ] [[package]] +name = "rancor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +dependencies = [ + "ptr_meta", +] + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2316,6 +2393,26 @@ dependencies = [ ] [[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "regex" version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2358,6 +2455,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] +name = "rend" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" + +[[package]] +name = "rkyv" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac" +dependencies = [ + "bytes", + "hashbrown 0.15.5", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "ropey" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2400,6 +2532,12 @@ dependencies = [ ] [[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2548,6 +2686,12 @@ dependencies = [ ] [[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2599,6 +2743,45 @@ dependencies = [ ] [[package]] +name = "sonic-number" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a74044c092f4f43ca7a6cfd62854cf9fb5ac8502b131347c990bf22bef1dfe" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "sonic-rs" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0e0c5c1c429b500b4583e860ed48f9e34968cb1ba49dd16c1e2743678e3fd18" +dependencies = [ + "ahash", + "bumpalo", + "bytes", + "cfg-if", + "faststr", + "itoa", + "ref-cast", + "ryu", + "serde", + "simdutf8", + "sonic-number", + "sonic-simd", + "thiserror", +] + +[[package]] +name = "sonic-simd" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b421f7b6aa4a5de8f685aaf398dfaa828346ee639d2b1c1061ab43d40baa6223" +dependencies = [ + "cfg-if", +] + +[[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2941,6 +3124,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2973,24 +3166,25 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -2999,9 +3193,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3009,9 +3203,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" dependencies = [ "proc-macro2", "quote", @@ -3022,9 +3216,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" +dependencies = [ + "unicode-ident", +] [[package]] name = "which" @@ -3310,6 +3507,26 @@ dependencies = [ ] [[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "zerofrom" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -52,6 +52,7 @@ futures-util = { version = "0.3", features = ["std", "async-await"], default-fea tokio-stream = "0.1.17" toml = "0.9" termina = "0.1" +sonic-rs = "0.5" [workspace.package] version = "25.7.1" diff --git a/helix-dap/Cargo.toml b/helix-dap/Cargo.toml index 8033c757..000ea5a8 100644 --- a/helix-dap/Cargo.toml +++ b/helix-dap/Cargo.toml @@ -26,7 +26,7 @@ slotmap.workspace = true futures-executor.workspace = true futures-util.workspace = true tokio-stream.workspace = true - +sonic-rs.workspace = true [dev-dependencies] fern = "0.7" diff --git a/helix-dap/src/lib.rs b/helix-dap/src/lib.rs index 16c84f66..4cb95315 100644 --- a/helix-dap/src/lib.rs +++ b/helix-dap/src/lib.rs @@ -13,7 +13,7 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum Error { #[error("failed to parse: {0}")] - Parse(#[from] serde_json::Error), + Parse(Box<dyn std::error::Error + Send + Sync>), #[error("IO Error: {0}")] IO(#[from] std::io::Error), #[error("request {0} timed out")] @@ -29,6 +29,18 @@ pub enum Error { } pub type Result<T> = core::result::Result<T, Error>; +impl From<serde_json::Error> for Error { + fn from(value: serde_json::Error) -> Self { + Self::Parse(Box::new(value)) + } +} + +impl From<sonic_rs::Error> for Error { + fn from(value: sonic_rs::Error) -> Self { + Self::Parse(Box::new(value)) + } +} + #[derive(Debug)] pub enum Request { RunInTerminal(<requests::RunInTerminal as types::Request>::Arguments), diff --git a/helix-dap/src/transport.rs b/helix-dap/src/transport.rs index 8ca408df..fdd60226 100644 --- a/helix-dap/src/transport.rs +++ b/helix-dap/src/transport.rs @@ -125,12 +125,14 @@ impl Transport { info!("[{}] <- DAP {}", id, msg); - // try parsing as output (server response) or call (server request) - let output: serde_json::Result<Payload> = serde_json::from_str(msg); + // NOTE: We avoid using `?` here, since it would return early on error + // and skip clearing `content`. By returning the result directly instead, + // we ensure `content.clear()` is always called. + let output = sonic_rs::from_slice(content).map_err(Into::into); content.clear(); - Ok(output?) + output } async fn recv_server_error( diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml index 20c3e78b..0607479e 100644 --- a/helix-lsp/Cargo.toml +++ b/helix-lsp/Cargo.toml @@ -31,3 +31,4 @@ parking_lot.workspace = true arc-swap = "1" slotmap.workspace = true thiserror.workspace = true +sonic-rs.workspace = true diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 450a3769..d01cd399 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -37,7 +37,7 @@ pub enum Error { #[error("protocol error: {0}")] Rpc(#[from] jsonrpc::Error), #[error("failed to parse: {0}")] - Parse(#[from] serde_json::Error), + Parse(Box<dyn std::error::Error + Send + Sync>), #[error("IO Error: {0}")] IO(#[from] std::io::Error), #[error("request {0} timed out")] @@ -52,6 +52,18 @@ pub enum Error { Other(#[from] anyhow::Error), } +impl From<serde_json::Error> for Error { + fn from(value: serde_json::Error) -> Self { + Self::Parse(Box::new(value)) + } +} + +impl From<sonic_rs::Error> for Error { + fn from(value: sonic_rs::Error) -> Self { + Self::Parse(Box::new(value)) + } +} + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum OffsetEncoding { /// UTF-8 code units aka bytes diff --git a/helix-lsp/src/transport.rs b/helix-lsp/src/transport.rs index 088c617b..fa4966c4 100644 --- a/helix-lsp/src/transport.rs +++ b/helix-lsp/src/transport.rs @@ -98,7 +98,7 @@ impl Transport { buffer.clear(); if reader.read_line(buffer).await? == 0 { return Err(Error::StreamClosed); - }; + } // debug!("<- header {:?}", buffer); @@ -133,12 +133,14 @@ impl Transport { info!("{language_server_name} <- {msg}"); - // try parsing as output (server response) or call (server request) - let output: serde_json::Result<ServerMessage> = serde_json::from_str(msg); + // NOTE: We avoid using `?` here, since it would return early on error + // and skip clearing `content`. By returning the result directly instead, + // we ensure `content.clear()` is always called. + let output = sonic_rs::from_slice(content).map_err(Into::into); content.clear(); - Ok(output?) + output } async fn recv_server_error( |