-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pg Client: improve Interval support (#1462)
* Refactor Pg Interval codec This a preliminary commit related to issue #1281 Encoding and decoding an Interval implied creating many objects (Duration and Period are immutable). Besides, the Duration.plusXXX and Period.normalized methods perform several computations. With the proposed change: - the codec doesn't create redundant objects - a decoded interval is always normalized (i.e. the number of months is strictly smaller than 12, the number of days is strictly smaller than 30,... etc). Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Added a JMH test for Interval encoding The test compares the previous and the proposed solutions. It confirms the assumptions about the proposed solution: - about twice as fast - removes pressure on GC # JMH version: 1.19 # VM version: JDK 1.8.0_422, VM 25.422-b05 # VM options: -Xms8g -Xmx8g -Xmn7g # Warmup: 20 iterations, 1 s each # Measurement: 10 iterations, 2 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time Benchmark Mode Cnt Score Error Units IntervalBenchmarks.encodeWithDurationAndPeriod thrpt 30 46339.530 ± 389.115 ops/ms IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.alloc.rate thrpt 30 3393.324 ± 28.481 MB/sec IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.alloc.rate.norm thrpt 30 96.000 ± 0.001 B/op IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.churn.PS_Eden_Space thrpt 30 3436.887 ± 778.345 MB/sec IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.churn.PS_Eden_Space.norm thrpt 30 97.302 ± 22.205 B/op IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.churn.PS_Survivor_Space thrpt 30 0.005 ± 0.006 MB/sec IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.churn.PS_Survivor_Space.norm thrpt 30 ≈ 10⁻⁴ B/op IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.count thrpt 30 36.000 counts IntervalBenchmarks.encodeWithDurationAndPeriod:·gc.time thrpt 30 30.000 ms IntervalBenchmarks.encodeWithParts thrpt 30 82322.542 ± 109.306 ops/ms IntervalBenchmarks.encodeWithParts:·gc.alloc.rate thrpt 30 ≈ 10⁻⁴ MB/sec IntervalBenchmarks.encodeWithParts:·gc.alloc.rate.norm thrpt 30 ≈ 10⁻⁶ B/op IntervalBenchmarks.encodeWithParts:·gc.count thrpt 30 ≈ 0 counts Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Interval conversion from/to Duration The conversion algorithm assumes a year last 12 months and a month lasts 30 days, as Postgres does and ISO 8601 suggests. See https://github.com/postgres/postgres/blob/5bbdfa8a18dc56d3e64aa723a68e02e897cb5ec3/src/include/datatype/timestamp.h#L116 Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Update vertx-pg-client/src/main/java/io/vertx/pgclient/data/Interval.java * Update vertx-pg-client/src/main/java/io/vertx/pgclient/data/Interval.java --------- Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
- Loading branch information
1 parent
91235f9
commit 3b29a6a
Showing
9 changed files
with
332 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!-- | ||
~ Copyright (c) 2011-2022 Contributors to the Eclipse Foundation | ||
~ | ||
~ This program and the accompanying materials are made available under the | ||
~ terms of the Eclipse Public License 2.0 which is available at | ||
~ http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
~ which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
~ | ||
~ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
--> | ||
|
||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd"> | ||
<id>benchmarks</id> | ||
<formats> | ||
<format>jar</format> | ||
</formats> | ||
<includeBaseDirectory>false</includeBaseDirectory> | ||
<fileSets> | ||
<fileSet> | ||
<directory>${project.build.testOutputDirectory}</directory> | ||
<outputDirectory>/</outputDirectory> | ||
</fileSet> | ||
</fileSets> | ||
<dependencySets> | ||
<dependencySet> | ||
<outputDirectory>/</outputDirectory> | ||
<unpack>true</unpack> | ||
<scope>test</scope> | ||
</dependencySet> | ||
</dependencySets> | ||
</assembly> |
84 changes: 84 additions & 0 deletions
84
vertx-pg-client/src/test/java/io/vertx/pgclient/benchmarks/IntervalBenchmarks.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright (c) 2011-2024 Contributors to the Eclipse Foundation | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
* which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
*/ | ||
|
||
package io.vertx.pgclient.benchmarks; | ||
|
||
import io.vertx.pgclient.data.Interval; | ||
import org.openjdk.jmh.annotations.*; | ||
import org.openjdk.jmh.infra.Blackhole; | ||
|
||
import java.io.IOException; | ||
import java.time.Duration; | ||
import java.time.Period; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import static java.time.temporal.ChronoUnit.MICROS; | ||
import static java.util.concurrent.TimeUnit.NANOSECONDS; | ||
|
||
@Threads(1) | ||
@State(Scope.Thread) | ||
@BenchmarkMode(Mode.Throughput) | ||
@OutputTimeUnit(TimeUnit.MILLISECONDS) | ||
@Warmup(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS) | ||
@Measurement(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS) | ||
@Fork(value = 3, jvmArgs = {"-Xms8g", "-Xmx8g", "-Xmn7g"}) | ||
public class IntervalBenchmarks { | ||
|
||
private Interval interval; | ||
|
||
@Setup | ||
public void setup() throws IOException, InterruptedException { | ||
interval = new Interval(-2, 3, 15, -13, 2, -57, -426994); | ||
} | ||
|
||
@Benchmark | ||
public void encodeWithDurationAndPeriod(Blackhole blackhole) { | ||
Duration duration = Duration | ||
.ofHours(interval.getHours()) | ||
.plusMinutes(interval.getMinutes()) | ||
.plusSeconds(interval.getSeconds()) | ||
.plus(interval.getMicroseconds(), MICROS); | ||
// days won't be changed | ||
Period monthYear = Period.of(interval.getYears(), interval.getMonths(), interval.getDays()).normalized(); | ||
|
||
blackhole.consume(NANOSECONDS.toMicros(duration.toNanos())); | ||
blackhole.consume(monthYear.getDays()); | ||
blackhole.consume((int) monthYear.toTotalMonths()); | ||
} | ||
|
||
@Benchmark | ||
public void encodeWithParts(Blackhole blackhole) { | ||
// We decompose the interval in 3 parts: months, seconds and micros | ||
int monthsPart = Math.addExact(Math.multiplyExact(interval.getYears(), 12), interval.getMonths()); | ||
// A long is big enough to store the maximum/minimum value of the seconds part | ||
long secondsPart = interval.getDays() * 24 * 3600L | ||
+ interval.getHours() * 3600L | ||
+ interval.getMinutes() * 60L | ||
+ interval.getSeconds() | ||
+ interval.getMicroseconds() / 1000000; | ||
int microsPart = interval.getMicroseconds() % 1000000; | ||
|
||
// The actual number of months is the sum of the months part and the number of months present in the seconds part | ||
int months = Math.addExact(monthsPart, Math.toIntExact(secondsPart / 2592000)); | ||
// The actual number of days is computed from the remainder of the previous division | ||
// It's necessarily smaller than or equal to 29 | ||
int days = (int) secondsPart % 2592000 / 86400; | ||
// The actual number of micros is the sum of the micros part and the remainder of previous divisions | ||
// The remainder of previous divisions is necessarily smaller than or equal to a day less a second | ||
// The microseconds part is smaller than a second | ||
// Therefore, their sum is necessarily smaller than a day | ||
long micros = microsPart + secondsPart % 2592000 % 86400 * 1000000; | ||
|
||
blackhole.consume(micros); | ||
blackhole.consume(days); | ||
blackhole.consume(months); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.