Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
505d233
Add JMH benchmarks for datetime format creation and performance evalu…
DmitryNekrasov Nov 12, 2025
de9dcd0
Introduce `ConcatenatedListView` for efficient list concatenation in …
DmitryNekrasov Nov 12, 2025
89cae15
Remove redundant type parameter `<T>` in `ParserStructure.simplify` m…
DmitryNekrasov Nov 12, 2025
9a12f57
Add unconditionalModifications after each step of simplification
DmitryNekrasov Nov 18, 2025
2619868
Rename `unconditionalModificationsForTails` to `unconditionalModifica…
DmitryNekrasov Nov 18, 2025
81f57fd
Refactor `ParserStructure` logic to use `buildList` for streamlined l…
DmitryNekrasov Nov 18, 2025
5d6e1f2
Refactor `ParserStructure` instantiation to improve formatting and re…
DmitryNekrasov Nov 18, 2025
8aa2569
Reorder `unconditionalModifications` placement in `ParserStructure`.
DmitryNekrasov Nov 18, 2025
ad637c9
Passes all tests and it has benchmarc score increase on Python dateti…
DmitryNekrasov Nov 18, 2025
999056f
Refactor `ParserStructure` logic to extract `mergeOperations` for cle…
DmitryNekrasov Nov 18, 2025
06dd152
Refactor `ParserStructure.concat` logic to simplify `mergeOperations`…
DmitryNekrasov Nov 18, 2025
5c90bdc
Add missing newline
DmitryNekrasov Nov 18, 2025
d88a303
Rename `operations` to `mergedOperations`.
DmitryNekrasov Nov 18, 2025
8271ac8
Simplify the ` mergedTails ` condition.
DmitryNekrasov Nov 19, 2025
885c3a7
Reorder and simplify `unconditionalModifications` handling in `Parser…
DmitryNekrasov Nov 19, 2025
f86b8fb
Refactor `ParserStructure` logic to streamline `mergedOperations` con…
DmitryNekrasov Nov 19, 2025
c17751b
Fix typo in comment: "number consumers" → "number of consumers".
DmitryNekrasov Nov 19, 2025
a02a32c
Refactor `mergedOperations` construction to reuse `operationsToMerge`…
DmitryNekrasov Nov 19, 2025
4a1f53c
Refactor `PythonDateTimeFormatBenchmark` into `CommonFormats`, update…
DmitryNekrasov Nov 19, 2025
11fc52c
Add benchmark for building four-digit UTC offset format
DmitryNekrasov Nov 19, 2025
f83a09e
Add benchmark for building RFC 1123 DateTime format
DmitryNekrasov Nov 19, 2025
61db0a9
Add benchmark for building ISO DateTime with offset format
DmitryNekrasov Nov 19, 2025
d49da73
Refactor RFC 1123 and UTC offset format benchmarks to use inline form…
DmitryNekrasov Nov 19, 2025
762d73d
Remove `ConcatenatedListView` as it is no longer in use.
DmitryNekrasov Nov 19, 2025
5e8fc06
Remove `SerialFormatBenchmark` as it is no longer in use.
DmitryNekrasov Nov 19, 2025
5752947
Update `ParallelFormatBenchmark` warmup and measurement parameters.
DmitryNekrasov Nov 19, 2025
f729ecc
Update copyright year range in `Parser.kt` header.
DmitryNekrasov Nov 19, 2025
07f8e77
Optimize concatenation of flat parsers.
DmitryNekrasov Nov 20, 2025
40b8dd3
Refactor `Parser` to streamline handling of accumulated operations.
DmitryNekrasov Nov 20, 2025
0f5f901
Add `SerialFormatBenchmark` for evaluating large format serialization…
DmitryNekrasov Nov 20, 2025
abdf1d4
Refactor `Parser` to replace `drop(1)` with an explicit loop for merg…
DmitryNekrasov Nov 21, 2025
e8e5424
Refactor `Parser` to apply `unconditionalModifications` after process…
DmitryNekrasov Nov 21, 2025
75599f8
Fix typo in comment within `Parser.kt`
DmitryNekrasov Nov 27, 2025
c8eb9b9
Document `mergeOperations` function with detailed explanation of para…
DmitryNekrasov Nov 27, 2025
c0a7cef
Fix the comment regarding unconditional modifications in `Parser.kt`.
DmitryNekrasov Nov 27, 2025
dbffa0a
Document `simplifyAndAppend` function with detailed explanation of be…
DmitryNekrasov Nov 27, 2025
ae3aed5
Improve comments in `Parser` for better clarity on reverse order proc…
DmitryNekrasov Nov 27, 2025
1a790c1
Document `concat` extension function in `Parser.kt` with details on b…
DmitryNekrasov Nov 27, 2025
e5f1966
Fix typos and clarify comments in `Parser.kt` regarding invariants an…
DmitryNekrasov Nov 27, 2025
394e7c0
Add validation check for non-empty operations in `mergeOperations` of…
DmitryNekrasov Nov 27, 2025
5875c72
Refactor `concat` function in `Parser.kt`, simplifying comments
DmitryNekrasov Nov 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions benchmarks/src/jmh/kotlin/CommonFormats.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Copyright 2019-2025 JetBrains s.r.o. and contributors.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

@file:Suppress("unused")

package kotlinx.datetime

import kotlinx.datetime.format.*
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.*

@Warmup(iterations = 20, time = 2)
@Measurement(iterations = 30, time = 2)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Fork(2)
open class CommonFormats {

@Benchmark
fun buildPythonDateTimeFormat(blackhole: Blackhole) {
val v = LocalDateTime.Format {
year()
char('-')
monthNumber()
char('-')
day()
char(' ')
hour()
char(':')
minute()
optional {
char(':')
second()
optional {
char('.')
secondFraction()
}
}
}
blackhole.consume(v)
}

@Benchmark
fun buildIsoDateTimeFormat(blackhole: Blackhole) {
val format = LocalDateTime.Format {
date(LocalDate.Format {
year()
char('-')
monthNumber()
char('-')
day()
})
alternativeParsing({ char('t') }) { char('T') }
time(LocalTime.Format {
hour()
char(':')
minute()
alternativeParsing({}) {
char(':')
second()
optional {
char('.')
secondFraction(1, 9)
}
}
})
}
blackhole.consume(format)
}

@Benchmark
fun buildFourDigitsUtcOffsetFormat(blackhole: Blackhole) {
val format = UtcOffset.Format {
offsetHours()
offsetMinutesOfHour()
}
blackhole.consume(format)
}

@Benchmark
fun buildRfc1123DateTimeFormat(blackhole: Blackhole) {
val format = DateTimeComponents.Format {
alternativeParsing({
// the day of week may be missing
}) {
dayOfWeek(DayOfWeekNames.ENGLISH_ABBREVIATED)
chars(", ")
}
day(Padding.NONE)
char(' ')
monthName(MonthNames.ENGLISH_ABBREVIATED)
char(' ')
year()
char(' ')
hour()
char(':')
minute()
optional {
char(':')
second()
}
chars(" ")
alternativeParsing({
chars("UT")
}, {
chars("Z")
}) {
optional("GMT") {
offset(UtcOffset.Format {
offsetHours()
offsetMinutesOfHour()
})
}
}
}
blackhole.consume(format)
}

@Benchmark
fun buildIsoDateTimeOffsetFormat(blackhole: Blackhole) {
val format = DateTimeComponents.Format {
date(LocalDate.Format {
year()
char('-')
monthNumber()
char('-')
day()
})
alternativeParsing({
char('t')
}) {
char('T')
}
hour()
char(':')
minute()
char(':')
second()
optional {
char('.')
secondFraction(1, 9)
}
alternativeParsing({
offsetHours()
}) {
offset(UtcOffset.Format {
alternativeParsing({ chars("z") }) {
optional("Z") {
offsetHours()
char(':')
offsetMinutesOfHour()
optional {
char(':')
offsetSecondsOfMinute()
}
}
}
})
}
}
blackhole.consume(format)
}
}
88 changes: 88 additions & 0 deletions benchmarks/src/jmh/kotlin/ParallelFormatBenchmark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2019-2025 JetBrains s.r.o. and contributors.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

@file:Suppress("unused")

package kotlinx.datetime

import kotlinx.datetime.format.alternativeParsing
import kotlinx.datetime.format.char
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit

@Warmup(iterations = 10, time = 2)
@Measurement(iterations = 20, time = 2)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Fork(1)
open class ParallelFormatBenchmark {

@Param("2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12")
var n = 0

@Benchmark
fun formatCreationWithAlternativeParsing(blackhole: Blackhole) {
val format = LocalDateTime.Format {
repeat(n) {
alternativeParsing(
{ monthNumber() },
{ day() },
primaryFormat = { hour() }
)
char('@')
minute()
char('#')
second()
}
}
blackhole.consume(format)
}

@Benchmark
fun formatCreationWithNestedAlternativeParsing(blackhole: Blackhole) {
val format = LocalDateTime.Format {
repeat(n) { index ->
alternativeParsing(
{ monthNumber(); char('-'); day() },
{ day(); char('/'); monthNumber() },
primaryFormat = { year(); char('-'); monthNumber(); char('-'); day() }
)

if (index and 1 == 0) {
alternativeParsing(
{
alternativeParsing(
{ hour(); char(':'); minute() },
{ minute(); char(':'); second() },
primaryFormat = { hour(); char(':'); minute(); char(':'); second() }
)
},
primaryFormat = {
year(); char('-'); monthNumber(); char('-'); day()
char('T')
hour(); char(':'); minute(); char(':'); second()
}
)
}

char('|')
if (index % 3 == 0) {
char('|')
}

if (index and 2 == 0) {
alternativeParsing(
{ char('Z') },
{ char('+'); hour(); char(':'); minute() },
primaryFormat = { char('-'); hour(); char(':'); minute() }
)
}
}
}
blackhole.consume(format)
}
}
45 changes: 45 additions & 0 deletions benchmarks/src/jmh/kotlin/SerialFormatBenchmark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2019-2025 JetBrains s.r.o. and contributors.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

@file:Suppress("unused")

package kotlinx.datetime

import kotlinx.datetime.format.char
import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import java.util.concurrent.TimeUnit

@Warmup(iterations = 10, time = 2)
@Measurement(iterations = 20, time = 2)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Fork(1)
open class SerialFormatBenchmark {

@Param("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024")
var n = 0

@Benchmark
fun largeSerialFormat(blackhole: Blackhole) {
val format = LocalDateTime.Format {
repeat(n) {
char('^')
monthNumber()
char('&')
day()
char('!')
hour()
char('$')
minute()
char('#')
second()
char('@')
}
}
blackhole.consume(format)
}
}
Loading