Skip to content

Add specific parser for mapper, delegate to generic parser as fallback - #7537

Open
RanVaknin wants to merge 2 commits into
feature/master/DDB-mapperv2from
rvaknin/ddb-mapper-date-fast-path
Open

RanVaknin wants to merge 2 commits into
feature/master/DDB-mapperv2from
rvaknin/ddb-mapper-date-fast-path

Conversation

@RanVaknin

Copy link
Copy Markdown
Contributor

Background

#7518 made Joda Time optional by replacing its date formatter and parser with the JDK date/time APIs. Those APIs process dates through general purpose intermediate representations: formatting expands the timestamp into calendar objects and uses decimal arithmetic for milliseconds, while parsing builds and resolves a map of date fields before converting it back to milliseconds. These temporary objects added roughly 600 bytes per write and 830 bytes per read.

This PR keeps the general JDK implementation as the compatibility fallback and adds a fast paths for the representation normally written by the mapper.

  • PUT: The mapper receives a Date, so it controls the stored representation. Dates with four digit years are written directly as the fixed 24 character UTC format, such as 2014-03-06T14:28:58.000Z. Dates outside that year range delegate to the the generic JDK formatter introduced in [DDB Mapper V2] Make Joda-Time an optional dependency #7518
  • GET: Stored strings may have been written by another application. The mapper first performs a cheap length and separator check. Strings matching the fixed 24 character format are parsed directly. Strings using another supported representation, such as numeric offsets, variable fractional digits, or non padded fields delegate to the generic JDK parser added in [DDB Mapper V2] Make Joda-Time an optional dependency #7518

Benchmarks

Targeted JMH benchmark on c6g.metal, Corretto 17.0.20, with 3 warmups, 3 measurements, 2 forks, and -prof gc.

I reused EnhancedClientGetV1MapperComparisonBenchmark and EnhancedClientPutV1MapperComparisonBenchmark that have been used for mapper testing, but seeded if with date fields so that they can exercise the new codepath. limited to SMALL and HUGE payloads:

class DateSmallBean {
    String hashKey;
    Date date;
    List<Calendar> dates; // 3 values
}

class DateHugeBean {
    String hashKey;
    Date date;
    Calendar calendar;
    List<Date> dates;                         // 32 values
    Map<String, Calendar> dateMap;             // 3 values
    Map<String, List<Date>> dateLists;         // 1 + 2 + 4 + 8 + 16 values
    Map<String, List<Map<String,
        List<Calendar>>>> nestedDates;         // 28 values
}

Results

Operation Payload Pre-#7518 ops/s This PR ops/s Delta Pre-#7518 B/op This PR B/op Allocation delta
GET DATE_SMALL 210,709 531,101 +152.1% 4,104 2,568 -37.4%
GET DATE_HUGE 11,326 48,716 +330.1% 61,440 24,616 -59.9%
PUT DATE_SMALL 451,788 862,983 +91.0% 2,576 2,400 -6.8%
PUT DATE_HUGE 24,652 71,010 +188.0% 34,024 27,880 -18.1%

@RanVaknin
RanVaknin requested a review from a team as a code owner November 10, 2026 21:41

@alextwoods alextwoods left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add the date to the existing benchmarks?

@RanVaknin

Copy link
Copy Markdown
Contributor Author

Should we add the date to the existing benchmarks?

It's not a bad idea, but the same can be said about all the other data types that we have converters for. I think at this point it's not as critical. Also we have #7300 that we can add these to.

What do you think?

@RanVaknin
RanVaknin force-pushed the rvaknin/ddb-mapper-date-fast-path branch from 84f1767 to 6d682c8 Compare November 12, 2026 01:17

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants