Skip to content

Improve performance of parse_from_rfc3339 #1735

@sby1ce

Description

@sby1ce

It would be nice to have performance of DateTime::parse_from_rfc3339 method match performance of speedate::DateTime::parse_str_rfc3339

Naively looking at both implementations the difference seems to come from avoiding bounds checking and unrolling scan::number loops

chrono/src/format/parse.rs

Lines 192 to 196 in f3fd15f

parsed.set_year(try_consume!(scan::number(s, 4, 4)))?;
s = scan::char(s, b'-')?;
parsed.set_month(try_consume!(scan::number(s, 2, 2)))?;
s = scan::char(s, b'-')?;
parsed.set_day(try_consume!(scan::number(s, 2, 2)))?;

https://github.com/pydantic/speedate/blob/54293aa5a1663148dfad90ccd818ade1d994476c/src/date.rs#L331-L361

        if bytes.len() < 10 {
            return Err(ParseError::TooShort);
        }
        let year: u16;
        let month: u8;
        let day: u8;
        unsafe {
            let y1 = get_digit_unchecked!(bytes, 0, InvalidCharYear) as u16;
            let y2 = get_digit_unchecked!(bytes, 1, InvalidCharYear) as u16;
            let y3 = get_digit_unchecked!(bytes, 2, InvalidCharYear) as u16;
            let y4 = get_digit_unchecked!(bytes, 3, InvalidCharYear) as u16;
            year = y1 * 1000 + y2 * 100 + y3 * 10 + y4;


            match bytes.get_unchecked(4) {
                b'-' => (),
                _ => return Err(ParseError::InvalidCharDateSep),
            }

Perhaps someone with more insight will correct me and actually the difference comes from Parsed struct or something like that.
I can write some microbenchmarks if this is something anyone is willing to look into

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions