From 3480feda7b572d33992544061a8e0fbf8610a803 Mon Sep 17 00:00:00 2001 From: Christophe Forycki Date: Mon, 1 Jul 2024 18:00:31 +0200 Subject: [PATCH 1/7] fix: indexmap minimal version with Map::shift_insert() --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e8ee3f27a..90e09adec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/serde-rs/json" rust-version = "1.56" [dependencies] -indexmap = { version = "2.2.1", optional = true } +indexmap = { version = "2.2.3", optional = true } itoa = "1.0" ryu = "1.0" serde = { version = "1.0.194", default-features = false } From bcedc3d96bcc33184f16d63eab397295e2193350 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Jul 2024 10:29:33 -0700 Subject: [PATCH 2/7] Release 1.0.120 --- Cargo.toml | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90e09adec..6a8e74526 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_json" -version = "1.0.119" +version = "1.0.120" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" diff --git a/src/lib.rs b/src/lib.rs index a4958efa1..f3da68dd6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,7 +299,7 @@ //! [macro]: crate::json //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.119")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.120")] // Ignored clippy lints #![allow( clippy::collapsible_else_if, From fcb5e83e44abe0f9c27c755a240a6ad56312c090 Mon Sep 17 00:00:00 2001 From: David Pathakjee Date: Tue, 2 Jul 2024 12:22:42 -0700 Subject: [PATCH 3/7] Correct documentation URL for Value's Index impl. The current id doesn't exist, so the link just goes to the top of the docs for Value, rather than to the intended section covering `impl Index for Value`. --- src/value/index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value/index.rs b/src/value/index.rs index 891ca8ef7..c56135b33 100644 --- a/src/value/index.rs +++ b/src/value/index.rs @@ -14,7 +14,7 @@ use core::ops; /// /// [`get`]: ../enum.Value.html#method.get /// [`get_mut`]: ../enum.Value.html#method.get_mut -/// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E +/// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E-for-Value /// /// This trait is sealed and cannot be implemented for types outside of /// `serde_json`. From 3f1c6de4af28b1f6c5100da323f2bffaf7c2083f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 11 Jul 2024 20:09:09 -0700 Subject: [PATCH 4/7] Ignore byte_char_slices clippy lint in test warning: can be more succinctly written as a byte str --> tests/test.rs:1108:13 | 1108 | &[b'"', b'\n', b'"'], | ^^^^^^^^^^^^^^^^^^^^ help: try: `b"\"\n\""` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#byte_char_slices = note: `-W clippy::byte-char-slices` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::byte_char_slices)]` warning: can be more succinctly written as a byte str --> tests/test.rs:1112:13 | 1112 | &[b'"', b'\x1F', b'"'], | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `b"\"\x1F\""` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#byte_char_slices --- tests/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test.rs b/tests/test.rs index c18254a85..71087162b 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,5 +1,6 @@ #![allow( clippy::assertions_on_result_states, + clippy::byte_char_slices, clippy::cast_precision_loss, clippy::derive_partial_eq_without_eq, clippy::excessive_precision, From 6a306e6ee9f47f3b37088217ffe3ebe9bbb54e5a Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Fri, 26 Jul 2024 20:00:43 +0300 Subject: [PATCH 5/7] Move call to tri! out of check_recursion! --- src/de.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index c7774f687..bfde371a1 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1870,8 +1870,9 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { Some(b'{') => { check_recursion! { self.eat_char(); - let value = tri!(visitor.visit_enum(VariantAccess::new(self))); + let ret = visitor.visit_enum(VariantAccess::new(self)); } + let value = tri!(ret); match tri!(self.parse_whitespace()) { Some(b'}') => { From b1edc7d13f72880fd0ac569403a409e5f7961d5f Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Sat, 27 Jul 2024 00:22:11 +0300 Subject: [PATCH 6/7] Optimize position search in error path Translating index into a line/column pair takes considerable time. Notably, the JSON benchmark modified to run on malformed data spends around 50% of the CPU time generating the error object. While it is generally assumed that the cold path is quite slow, such a drastic pessimization may be unexpected, especially when a faster implementation exists. Using vectorized routines provided by the memchr crate increases performance of the failure path by 2x on average. Old implementation: DOM STRUCT data/canada.json 122 MB/s 168 MB/s data/citm_catalog.json 135 MB/s 195 MB/s data/twitter.json 142 MB/s 226 MB/s New implementation: DOM STRUCT data/canada.json 216 MB/s 376 MB/s data/citm_catalog.json 238 MB/s 736 MB/s data/twitter.json 210 MB/s 492 MB/s In comparison, the performance of the happy path is: DOM STRUCT data/canada.json 283 MB/s 416 MB/s data/citm_catalog.json 429 MB/s 864 MB/s data/twitter.json 275 MB/s 541 MB/s While this introduces a new dependency, memchr is much faster to compile than serde, so compile time does not increase significantly. Additionally, memchr provides a more efficient SWAR-based implementation of both the memchr and count routines even without std, providing benefits for embedded uses as well. --- Cargo.toml | 3 ++- src/read.rs | 19 +++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a8e74526..8f8b45582 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ rust-version = "1.56" [dependencies] indexmap = { version = "2.2.3", optional = true } itoa = "1.0" +memchr = { version = "2", default-features = false } ryu = "1.0" serde = { version = "1.0.194", default-features = false } @@ -45,7 +46,7 @@ features = ["raw_value"] [features] default = ["std"] -std = ["serde/std"] +std = ["memchr/std", "serde/std"] # Provide integration for heap-allocated collections without depending on the # rest of the Rust standard library. diff --git a/src/read.rs b/src/read.rs index a426911c7..e03e13f28 100644 --- a/src/read.rs +++ b/src/read.rs @@ -415,19 +415,14 @@ impl<'a> SliceRead<'a> { } fn position_of_index(&self, i: usize) -> Position { - let mut position = Position { line: 1, column: 0 }; - for ch in &self.slice[..i] { - match *ch { - b'\n' => { - position.line += 1; - position.column = 0; - } - _ => { - position.column += 1; - } - } + let start_of_line = match memchr::memrchr(b'\n', &self.slice[..i]) { + Some(position) => position + 1, + None => 0, + }; + Position { + line: 1 + memchr::memchr_iter(b'\n', &self.slice[..start_of_line]).count(), + column: i - start_of_line, } - position } /// The big optimization here over IoRead is that if the string contains no From eca2658a22cb39952783cb6914eb18242659f66a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Jul 2024 14:03:27 -0700 Subject: [PATCH 7/7] Release 1.0.121 --- Cargo.toml | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8f8b45582..9fd5fc7f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_json" -version = "1.0.120" +version = "1.0.121" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" diff --git a/src/lib.rs b/src/lib.rs index f3da68dd6..3225e26f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,7 +299,7 @@ //! [macro]: crate::json //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.120")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.121")] // Ignored clippy lints #![allow( clippy::collapsible_else_if,