Skip to content

Commit 2aca4d1

Browse files
committed
psql-srv: Use optimized date+time encoding
This commit replaces our usage of chrono's `format()` methods with our handwritten optimized encoding algorithms in psql-srv in the code we use to encode rows before sending them over the wire. This significantly improves warm read time for queries that include timestamps in their result sets. Release-Note-Core: Significantly improved warm read performance for certain queries that return timestamps Change-Id: I4b1158b20d9052bae204b6b1584b6020d8fd504a Reviewed-on: https://gerrit.readyset.name/c/readyset/+/7221 Reviewed-by: Luke Osborne <luke@readyset.io> Tested-by: Buildkite CI
1 parent 870b8b8 commit 2aca4d1

File tree

3 files changed

+7
-40
lines changed

3 files changed

+7
-40
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

psql-srv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ uuid = "0.8"
4040
nom-sql = { path = "../nom-sql" }
4141
readyset-adapter-types = { path = "../readyset-adapter-types" }
4242
readyset-data = { path = "../readyset-data" }
43+
readyset-util = { path = "../readyset-util" }
4344

4445
[dev-dependencies]
4546
tokio = { workspace = true, features = ["full"] }

psql-srv/src/codec/encoder.rs

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use bytes::{BufMut, BytesMut};
44
use eui48::MacAddressFormat;
55
use postgres::error::ErrorPosition;
66
use postgres_types::{ToSql, Type};
7+
use readyset_util::fmt::FastEncode;
78
use tokio_util::codec::Encoder;
89

910
use crate::codec::error::EncodeError as Error;
@@ -76,10 +77,6 @@ const LENGTH_NULL_SENTINEL: i32 = -1;
7677
const LENGTH_PLACEHOLDER: i32 = -1;
7778
const NUL_BYTE: u8 = b'\0';
7879
const NUL_CHAR: char = '\0';
79-
const TIMESTAMP_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.f";
80-
const TIMESTAMP_TZ_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.f %:z";
81-
const TIME_FORMAT: &str = "%H:%M:%S%.f";
82-
const DATE_FORMAT: &str = "%Y-%m-%d";
8380

8481
impl Encoder<BackendMessage> for Codec {
8582
type Error = Error;
@@ -647,18 +644,18 @@ fn put_text_value(val: PsqlValue, dst: &mut BytesMut) -> Result<(), Error> {
647644
PsqlValue::Timestamp(v) => {
648645
// TODO: Does not correctly handle all valid timestamp representations. For example,
649646
// 8601/SQL timestamp format is assumed; infinity/-infinity are not supported.
650-
write!(dst, "{}", v.format(TIMESTAMP_FORMAT))?;
647+
v.put(dst);
651648
}
652649
PsqlValue::TimestampTz(v) => {
653650
// TODO: Does not correctly handle all valid timestamp representations. For example,
654651
// 8601/SQL timestamp format is assumed; infinity/-infinity are not supported.
655-
write!(dst, "{}", v.format(TIMESTAMP_TZ_FORMAT))?;
652+
v.put(dst);
656653
}
657654
PsqlValue::Date(v) => {
658-
write!(dst, "{}", v.format(DATE_FORMAT))?;
655+
v.put(dst);
659656
}
660657
PsqlValue::Time(v) => {
661-
write!(dst, "{}", v.format(TIME_FORMAT))?;
658+
v.put(dst);
662659
}
663660
PsqlValue::ByteArray(b) => {
664661
write!(
@@ -1644,22 +1641,6 @@ mod tests {
16441641
assert_eq!(buf, exp);
16451642
}
16461643

1647-
#[test]
1648-
fn test_encode_text_timestamp() {
1649-
let mut buf = BytesMut::new();
1650-
put_text_value(
1651-
PsqlValue::Timestamp(
1652-
NaiveDateTime::parse_from_str("2020-01-02 03:04:05.660", TIMESTAMP_FORMAT).unwrap(),
1653-
),
1654-
&mut buf,
1655-
)
1656-
.unwrap();
1657-
let mut exp = BytesMut::new();
1658-
exp.put_i32(23); // length
1659-
exp.extend_from_slice(b"2020-01-02 03:04:05.660"); // value
1660-
assert_eq!(buf, exp);
1661-
}
1662-
16631644
#[test]
16641645
fn test_encode_text_bytea() {
16651646
let mut buf = BytesMut::new();
@@ -1735,20 +1716,4 @@ mod tests {
17351716
put_text_value(PsqlValue::Bit(bits), &mut buf).unwrap();
17361717
assert_eq!(buf, exp);
17371718
}
1738-
1739-
#[test]
1740-
fn test_encode_text_timestamp_tz() {
1741-
let dt = FixedOffset::east_opt(18000)
1742-
.unwrap()
1743-
.from_utc_datetime(&NaiveDateTime::new(
1744-
NaiveDate::from_ymd_opt(2020, 1, 2).unwrap(),
1745-
NaiveTime::from_hms_milli_opt(3, 4, 5, 660).unwrap(),
1746-
));
1747-
let mut buf = BytesMut::new();
1748-
put_text_value(PsqlValue::TimestampTz(dt), &mut buf).unwrap();
1749-
let mut exp = BytesMut::new();
1750-
exp.put_i32(30);
1751-
exp.extend_from_slice(b"2020-01-02 08:04:05.660 +05:00");
1752-
assert_eq!(buf, exp);
1753-
}
17541719
}

0 commit comments

Comments
 (0)