Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize serialization for client parameters #864

Merged
merged 42 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f28b449
core: Fix doc typo
lexnv Aug 24, 2022
febd278
types: Implement generic `ParamBuilder` for RPC parameters
lexnv Aug 24, 2022
d50de5e
types: Add specialized RPC parameter builder for arrays and maps
lexnv Aug 24, 2022
7af14ff
types: Implement parameter builder for batch requests
lexnv Aug 26, 2022
98c0058
types: Implement `rpc_params` in the `types` crate
lexnv Aug 26, 2022
bf7cd86
core: Adjust `ClientT` for generic efficient parameters
lexnv Aug 26, 2022
32c5f51
proc-macro: Render clients using the parameter builders
lexnv Aug 26, 2022
1bc535f
Adjust testing to the `ToRpcParams` interface
lexnv Aug 26, 2022
315ee89
core: Move `rpc_params` to core and simplify testing
lexnv Aug 26, 2022
555f53b
core: Rename server's trait to `ToRpcServerParams`
lexnv Aug 26, 2022
92f9e9e
bench: Adjust benches to the `ToRpcParams` interface
lexnv Aug 29, 2022
cf941b7
Fix clippy
lexnv Aug 29, 2022
c48cc4a
types: Rename batch builder to `BatchRequestBuilder`
lexnv Aug 29, 2022
89b03c5
examples: Re-enable proc-macro example
lexnv Aug 29, 2022
07a888f
types: Fix doc tests and add panic documentation
lexnv Aug 29, 2022
faf016c
core: Fix documentation link
lexnv Aug 29, 2022
7485bbc
client: Use BatchRequestBuilder as parameter for batch requests
lexnv Aug 30, 2022
0e3e58e
Update core/src/server/rpc_module.rs
lexnv Aug 31, 2022
ee213d5
Update core/src/server/rpc_module.rs
lexnv Aug 31, 2022
b460c94
types: Add specialized constructors for internal `ParamsBuilder`
lexnv Aug 31, 2022
706a672
types: Implement `EmptyParams` for client's parameters
lexnv Aug 31, 2022
0d80222
tests: Fix macos disabled test
lexnv Aug 31, 2022
20e357b
types: Improve comment
lexnv Aug 31, 2022
9590d1e
Fix clippy
lexnv Aug 31, 2022
4789f9e
benches: Rename functions
lexnv Aug 31, 2022
6f097b7
types: Rename param types to `ArrayParams` and `ObjectParams`
lexnv Aug 31, 2022
7df0f55
Move paramters to core crate
lexnv Aug 31, 2022
22f31dc
core: Return `core::Error` from `ToRpcParams` trait
lexnv Aug 31, 2022
0129bec
Fix doc link
lexnv Aug 31, 2022
0d2ccd8
Fix `ArrayParamsBuilder` doc links
lexnv Sep 1, 2022
126c27a
Remove `ToRpcServerParams` trait
lexnv Sep 1, 2022
a9a582d
core: Fix `ToRpcParams` docs
lexnv Sep 2, 2022
83d94c6
Remove `ParamsSer` and extend benchmarking
lexnv Sep 2, 2022
bbdcc38
core: Optimise `rpc_params` to avoid allocation on error
lexnv Sep 2, 2022
e09181a
params: zero allocation for empty params
lexnv Sep 2, 2022
5c85471
examples: Add copyright back
lexnv Sep 2, 2022
202d5bc
traits: Remove empty doc line
lexnv Sep 2, 2022
5a4a463
Update core/src/traits.rs
lexnv Sep 2, 2022
c1f1dcb
Update core/src/traits.rs
lexnv Sep 2, 2022
2fabe37
examples: Restore `proc_macro` example to origin/master
lexnv Sep 5, 2022
75d6b8b
core: Remove empty case for `rpc_params` macro
lexnv Sep 5, 2022
c85670e
Merge remote-tracking branch 'origin/862_param_ser_v4' into 862_param…
lexnv Sep 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove ParamsSer and extend benchmarking
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
  • Loading branch information
lexnv committed Sep 2, 2022
commit 83d94c60ab13e3f9e4dce49342aa1cab7789ced4
36 changes: 26 additions & 10 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use futures_util::future::{join_all, FutureExt};
use futures_util::stream::FuturesUnordered;
use helpers::{http_client, ws_client, SUB_METHOD_NAME, UNSUB_METHOD_NAME};
use jsonrpsee::core::client::{ClientT, SubscriptionClientT};
use jsonrpsee::core::params::{ArrayParamsBuilder, BatchRequestBuilder, EmptyParams};
use jsonrpsee::core::params::{ArrayParamsBuilder, BatchRequestBuilder, EmptyParams, ObjectParamsBuilder};
use jsonrpsee::core::traits::ToRpcParams;
use jsonrpsee::http_client::HeaderMap;
use jsonrpsee::types::{Id, ParamsSer, RequestSer};
use jsonrpsee::types::{Id, RequestSer};
use pprof::criterion::{Output, PProfProfiler};
use tokio::runtime::Runtime as TokioRuntime;

Expand Down Expand Up @@ -65,21 +65,17 @@ fn v2_serialize(req: RequestSer<'_>) -> String {
}

pub fn jsonrpsee_types_v2(crit: &mut Criterion) {
// Construct the serialized request using the `ParamsSer` directly.
crit.bench_function("jsonrpsee_types_baseline_params", |b| {
// Construct the serialized array request using the `RawValue` directly.
crit.bench_function("jsonrpsee_types_array_params_baseline", |b| {
b.iter(|| {
lexnv marked this conversation as resolved.
Show resolved Hide resolved
let params = &[1_u64.into(), 2_u32.into()];
let params = ParamsSer::ArrayRef(params);
let params = serde_json::to_string(&params).unwrap();
let params = serde_json::value::RawValue::from_string(params).unwrap();
let params = serde_json::value::RawValue::from_string("[1, 2]".to_string()).unwrap();

let request = RequestSer::new(&Id::Number(0), "say_hello", Some(params));
v2_serialize(request);
})
});

// Construct the serialized request using the `ArrayParamsBuilder`.
crit.bench_function("jsonrpsee_types_unnamed_params", |b| {
crit.bench_function("jsonrpsee_types_array_params", |b| {
b.iter(|| {
let mut builder = ArrayParamsBuilder::new();
builder.insert(1u64).unwrap();
Expand All @@ -89,6 +85,26 @@ pub fn jsonrpsee_types_v2(crit: &mut Criterion) {
v2_serialize(request);
})
});

// Construct the serialized object request using the `RawValue` directly.
crit.bench_function("jsonrpsee_types_object_params_baseline", |b| {
b.iter(|| {
let params = serde_json::value::RawValue::from_string(r#"{"key": 1}"#.to_string()).unwrap();

let request = RequestSer::new(&Id::Number(0), "say_hello", Some(params));
v2_serialize(request);
})
});
// Construct the serialized request using the `ObjectParamsBuilder`.
crit.bench_function("jsonrpsee_types_object_params", |b| {
b.iter(|| {
let mut builder = ObjectParamsBuilder::new();
builder.insert("key", 1u32).unwrap();
let params = builder.build().to_rpc_params().expect("Valid params");
let request = RequestSer::new(&Id::Number(0), "say_hello", params);
v2_serialize(request);
})
});
}

trait RequestBencher {
Expand Down
2 changes: 1 addition & 1 deletion types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub mod response;
pub mod error;

pub use error::{ErrorObject, ErrorObjectOwned, ErrorResponse, SubscriptionEmptyError, SubscriptionResult};
pub use params::{Id, Params, ParamsSequence, ParamsSer, SubscriptionId, TwoPointZero};
pub use params::{Id, Params, ParamsSequence, SubscriptionId, TwoPointZero};
pub use request::{InvalidRequest, Notification, NotificationSer, Request, RequestSer};
pub use response::{Response, SubscriptionPayload, SubscriptionResponse};

Expand Down
54 changes: 1 addition & 53 deletions types/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
use std::fmt;

use crate::error::CallError;
use alloc::collections::BTreeMap;
use anyhow::anyhow;
use beef::Cow;
use serde::de::{self, Deserializer, Unexpected, Visitor};
Expand Down Expand Up @@ -260,40 +259,6 @@ impl<'a> ParamsSequence<'a> {
}
}

/// [Serializable JSON-RPC parameters](https://www.jsonrpc.org/specification#parameter_structures)
///
/// If your type implements `Into<JsonValue>`, call that in favor of `serde_json::to:value` to
/// construct the parameters. Because `serde_json::to_value` serializes the type which allocates
/// whereas `Into<JsonValue>` doesn't in most cases.
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum ParamsSer<'a> {
/// Positional params (heap allocated).
Array(Vec<JsonValue>),
/// Positional params (slice).
ArrayRef(&'a [JsonValue]),
/// Params by name.
Map(BTreeMap<&'a str, JsonValue>),
}

impl<'a> From<BTreeMap<&'a str, JsonValue>> for ParamsSer<'a> {
fn from(map: BTreeMap<&'a str, JsonValue>) -> Self {
Self::Map(map)
}
}

impl<'a> From<Vec<JsonValue>> for ParamsSer<'a> {
fn from(arr: Vec<JsonValue>) -> Self {
Self::Array(arr)
}
}

impl<'a> From<&'a [JsonValue]> for ParamsSer<'a> {
fn from(slice: &'a [JsonValue]) -> Self {
Self::ArrayRef(slice)
}
}

/// Id of a subscription, communicated by the server.
#[derive(Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
Expand Down Expand Up @@ -410,7 +375,7 @@ impl<'a> Id<'a> {

#[cfg(test)]
mod test {
use super::{Cow, Id, JsonValue, Params, ParamsSer, SubscriptionId, TwoPointZero};
use super::{Cow, Id, JsonValue, Params, SubscriptionId, TwoPointZero};
use crate::response::SubscriptionPayload;

#[test]
Expand Down Expand Up @@ -449,23 +414,6 @@ mod test {
assert_eq!(serialized, r#"[null,0,2,3,"\"3","test"]"#);
}

#[test]
fn params_serialize() {
let test_vector = &[
("[]", ParamsSer::Array(serde_json::from_str("[]").unwrap())),
("[42,23]", ParamsSer::Array(serde_json::from_str("[42,23]").unwrap())),
(
r#"{"a":42,"b":null,"c":"aa"}"#,
ParamsSer::Map(serde_json::from_str(r#"{"a":42,"b":null,"c":"aa"}"#).unwrap()),
),
];

for (initial_ser, params) in test_vector {
let serialized = serde_json::to_string(params).unwrap();
assert_eq!(&serialized, initial_ser);
}
}

#[test]
fn params_parse() {
let none = Params::new(None);
Expand Down