Skip to content

Commit

Permalink
Minor optimisations
Browse files Browse the repository at this point in the history
* Mark the error branches as cold to help the compiler optimising for
the other case
* Mark some functions as inline

Both changes have been benchmarked and have shown minor performance improvements
  • Loading branch information
weiznich committed May 24, 2024
1 parent 3e10a04 commit c19ace7
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 24 deletions.
10 changes: 3 additions & 7 deletions diesel/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::result;

use crate::backend::Backend;
use crate::expression::select_by::SelectBy;
use crate::result::DeserializeFieldError;
use crate::row::{NamedRow, Row};
use crate::sql_types::{SingleValue, SqlType, Untyped};
use crate::Selectable;
Expand Down Expand Up @@ -543,13 +542,10 @@ where
let field = row.get(0).ok_or(crate::result::UnexpectedEndOfRow)?;
T::from_nullable_sql(field.value()).map_err(|e| {
if e.is::<crate::result::UnexpectedNullError>() {
return e;
e
} else {
Box::new(crate::result::DeserializeFieldError::new(field, e))
}

Box::new(DeserializeFieldError {
field_name: field.field_name().map(|s| s.to_string()),
error: e,
})
})
}
}
Expand Down
1 change: 1 addition & 0 deletions diesel/src/pg/connection/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ impl PgResult {
)
}

#[inline(always)] // benchmarks indicate a ~1.7% improvement in instruction count for this
pub(super) fn column_name(&self, col_idx: usize) -> Option<&str> {
self.column_name_map
.get_or_init(|| {
Expand Down
37 changes: 20 additions & 17 deletions diesel/src/pg/types/integers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,20 @@ impl ToSql<sql_types::Oid, Pg> for u32 {

#[cfg(feature = "postgres_backend")]
impl FromSql<sql_types::SmallInt, Pg> for i16 {
#[inline(always)]
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
let mut bytes = value.as_bytes();
if bytes.len() < 2 {
return deserialize::Result::Err(
return emit_size_error(
"Received less than 2 bytes while decoding an i16. \
Was an expression of a different type accidentally marked as SmallInt?"
.into(),
Was an expression of a different type accidentally marked as SmallInt?",
);
}

if bytes.len() > 2 {
return deserialize::Result::Err(
return emit_size_error(
"Received more than 2 bytes while decoding an i16. \
Was an Integer expression accidentally marked as SmallInt?"
.into(),
Was an Integer expression accidentally marked as SmallInt?",
);
}
bytes
Expand All @@ -48,21 +47,20 @@ impl FromSql<sql_types::SmallInt, Pg> for i16 {

#[cfg(feature = "postgres_backend")]
impl FromSql<sql_types::Integer, Pg> for i32 {
#[inline(always)]
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
let mut bytes = value.as_bytes();
if bytes.len() < 4 {
return deserialize::Result::Err(
return emit_size_error(
"Received less than 4 bytes while decoding an i32. \
Was an SmallInt expression accidentally marked as Integer?"
.into(),
Was an SmallInt expression accidentally marked as Integer?",
);
}

if bytes.len() > 4 {
return deserialize::Result::Err(
return emit_size_error(
"Received more than 4 bytes while decoding an i32. \
Was an BigInt expression accidentally marked as Integer?"
.into(),
Was an BigInt expression accidentally marked as Integer?",
);
}
bytes
Expand All @@ -71,23 +69,28 @@ impl FromSql<sql_types::Integer, Pg> for i32 {
}
}

#[cold]
#[inline(never)]
fn emit_size_error<T>(var_name: &str) -> deserialize::Result<T> {
deserialize::Result::Err(var_name.into())
}

#[cfg(feature = "postgres_backend")]
impl FromSql<sql_types::BigInt, Pg> for i64 {
#[inline(always)]
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
let mut bytes = value.as_bytes();
if bytes.len() < 8 {
return deserialize::Result::Err(
return emit_size_error(
"Received less than 8 bytes while decoding an i64. \
Was an Integer expression accidentally marked as BigInt?"
.into(),
Was an Integer expression accidentally marked as BigInt?",
);
}

if bytes.len() > 8 {
return deserialize::Result::Err(
return emit_size_error(
"Received more than 8 bytes while decoding an i64. \
Was an expression of a different type expression accidentally marked as BigInt?"
.into(),
);
}
bytes
Expand Down
14 changes: 14 additions & 0 deletions diesel/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,20 @@ pub struct DeserializeFieldError {
pub error: Box<dyn StdError + Send + Sync>,
}

impl DeserializeFieldError {
#[cold]
pub(crate) fn new<'a, F, DB>(field: F, error: Box<dyn std::error::Error + Send + Sync>) -> Self
where
DB: crate::backend::Backend,
F: crate::row::Field<'a, DB>,
{
DeserializeFieldError {
field_name: field.field_name().map(|s| s.to_string()),
error,
}
}
}

impl StdError for DeserializeFieldError {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
Some(&*self.error)
Expand Down
1 change: 1 addition & 0 deletions diesel_bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fast_run = []

[profile.release]
lto = true
debug = true
codegen-units = 1

[patch.crates-io]
Expand Down

0 comments on commit c19ace7

Please sign in to comment.