Skip to content

Commit

Permalink
Soft-inline Thrift (de)serialization functions
Browse files Browse the repository at this point in the history
Summary:
**TL;DR Inlining Thrift (de)serialization functions significantly improves observed wall clock latencies for almost all workloads with only minimal impact to binary size but a measurable impact to build times.**

If this proposal sounds familiar, it's because it's an updated version of [this one](https://fb.workplace.com/groups/rust.libraries.wg/posts/2267253036959522/) and this diff D57312501 :)

Full RFC and discussion in [this post](https://fb.workplace.com/groups/rust.libraries.wg/permalink/2268674973483995/).

In local tests, using the Thrift loadgen framework to attempt a consistent QPS for reproducibility, results were overall positive in reducing observed latency.

Overall, in numbers:
* 49.63% improvement for P50
* 49.95% improvement for AVG
* 62.41% improvement for P99

Automated build time regression analysis found that there was a 30%-40% increase in build times for the NodeAPI compiler (P1364121390 - wall clock, 1m-4m regression). This is actually an improvement over the previous regression of 400%-500% (P1364124026) for the `#[inline(always)]` version.

Reviewed By: jsgf, shayne-fletcher

Differential Revision: D57419887

fbshipit-source-id: 5ed0b3056c2a3dc5c17cb95b4982aa9d862fbcf2
  • Loading branch information
Pedro Rittner authored and facebook-github-bot committed May 16, 2024
1 parent fc45a44 commit b2732cf
Show file tree
Hide file tree
Showing 38 changed files with 718 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_set_begin(
<{{#type:set_elem_type}}{{>lib/type}}{{/type:set_elem_type}} as ::fbthrift::GetTType>::TTYPE,
Expand All @@ -65,6 +66,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
let (_elem_ty, len) = p.read_set_begin()?;
let mut set = <{{>lib/type}}>::with_capacity(len.unwrap_or_default());
Expand Down Expand Up @@ -100,6 +102,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_map_begin(
<{{#type:key_type}}{{>lib/type}}{{/type:key_type}} as ::fbthrift::GetTType>::TTYPE,
Expand All @@ -120,6 +123,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
let (_key_ty, _val_ty, len) = p.read_map_begin()?;
let mut map = <{{>lib/type}}>::with_capacity(len.unwrap_or_default());
Expand Down Expand Up @@ -157,6 +161,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
self.0.as_slice().write(p)
}
Expand All @@ -166,6 +171,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
p.read_binary()
}
Expand All @@ -191,6 +197,7 @@
P: ::fbthrift::ProtocolWriter,
{{>lib/type}}: ::fbthrift::Serialize<P>,
{
#[inline]
fn write(&self, p: &mut P) {
self.0.write(p)
}
Expand All @@ -201,6 +208,7 @@
P: ::fbthrift::ProtocolReader,
{{>lib/type}}: ::fbthrift::Deserialize<P>,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
Ok(LocalImpl({{>lib/type}}::read(p)?))
}
Expand All @@ -215,6 +223,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_set_begin(
<{{#type:set_elem_type}}{{>lib/type}}{{/type:set_elem_type}} as ::fbthrift::GetTType>::TTYPE,
Expand All @@ -232,6 +241,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
let (_elem_ty, len) = p.read_set_begin()?;
let mut set = <{{>lib/annfieldtype}}>::with_capacity(len.unwrap_or_default());
Expand Down Expand Up @@ -267,6 +277,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_map_begin(
<{{#type:key_type}}{{>lib/type}}{{/type:key_type}} as ::fbthrift::GetTType>::TTYPE,
Expand All @@ -287,6 +298,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
let (_key_ty, _val_ty, len) = p.read_map_begin()?;
let mut map = <{{>lib/annfieldtype}}>::with_capacity(len.unwrap_or_default());
Expand Down Expand Up @@ -324,6 +336,7 @@
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
self.0.as_slice().write(p)
}
Expand All @@ -333,6 +346,7 @@
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
p.read_binary()
}
Expand All @@ -358,6 +372,7 @@
P: ::fbthrift::ProtocolWriter,
{{>lib/annfieldtype}}: ::fbthrift::Serialize<P>,
{
#[inline]
fn write(&self, p: &mut P) {
self.0.write(p)
}
Expand All @@ -368,6 +383,7 @@
P: ::fbthrift::ProtocolReader,
{{>lib/annfieldtype}}: ::fbthrift::Deserialize<P>,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
Ok(LocalImpl({{>lib/annfieldtype}}::read(p)?))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl<P> ::fbthrift::Serialize<P> for self::{{struct:rust_name}}
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_struct_begin("{{struct:name}}");{{!
}}{{#struct:fields}}{{!
Expand Down Expand Up @@ -137,6 +138,7 @@ impl<P> ::fbthrift::Deserialize<P> for self::{{struct:rust_name}}
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
static FIELDS: &[::fbthrift::Field] = &[
{{#struct:fields_by_name}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl<P> ::fbthrift::Serialize<P> for {{typedef:rust_name}}
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
{{program:crate}}::r#impl::write(&self.0, p)
}
Expand All @@ -40,6 +41,7 @@ impl<P> ::fbthrift::Deserialize<P> for {{typedef:rust_name}}
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
{{program:crate}}::r#impl::read(p).map({{typedef:rust_name}})
}
Expand All @@ -52,6 +54,7 @@ impl<P> ::fbthrift::Serialize<P> for {{typedef:rust_name}}
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
{{#typedef:has_adapter?}}{{!
}}{{>lib/adapter/qualified}}::to_thrift(&self.0).write(p){{!
Expand All @@ -66,6 +69,7 @@ impl<P> ::fbthrift::Deserialize<P> for {{typedef:rust_name}}
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
{{#typedef:has_adapter?}}{{!
}}{{>lib/adapter/qualified}}::from_thrift({{!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl<P> ::fbthrift::Serialize<P> for {{struct:rust_name}}
where
P: ::fbthrift::ProtocolWriter,
{
#[inline]
fn write(&self, p: &mut P) {
p.write_struct_begin("{{struct:name}}");
match self {{>lib/block}}{{!
Expand Down Expand Up @@ -69,6 +70,7 @@ impl<P> ::fbthrift::Deserialize<P> for {{struct:rust_name}}
where
P: ::fbthrift::ProtocolReader,
{
#[inline]
fn read(p: &mut P) -> ::anyhow::Result<Self> {
static FIELDS: &[::fbthrift::Field] = &[
{{#struct:fields_by_name}}
Expand Down

0 comments on commit b2732cf

Please sign in to comment.