Skip to content

Commit fed744b

Browse files
authored
Revamp the Kotlin Vert.x portions "vertx-web-kotlinx" and "vertx-web-kotlin-coroutines" (#9374)
* Revamp the "vertx-web-kotlinx" portion project Changes: 1. bump the Gradle versions and the dependency versions to the latest 1. bump the JVM version to 21 with the new `jvmToolchain` DSL 1. resolve deprecations 1. update the dockerfile to use the `installDist` Gradle task so the time for archiving and unarchiving is saved * Run the revamped benchmark There are no build or runtime errors. Single query performance seems to have been improved by 2% with the bumped versions (I think most likely due to Java 21). Vagrant reduces performance by about 20% compared to running directly with Docker. * Enable io_uring and run the benchmark The single query performance is improved by 5% - 10%. * Try fixing the performance issues of the "vertx-web-kotlinx" portion in the "single query" and "JSON serialization" tests in the [Continuous Benchmarking results](https://tfb-status.techempower.com/) by using static kotlinx.serialization serializers The "vertx-web-kotlinx" results in the Continuous Benchmarking results are much lower than those of the "vertx-web-kotlin-coroutines" portion. See [the latest results](https://www.techempower.com/benchmarks/#section=test&runid=592cab59-a9db-463b-a9c9-33d2f9484e92&hw=ph&test=db) for example. Looking at the "single query" results, I first suspected that it was caused by there being not enough memory for the JVM runtime, so I added some logging code that prints the memory usage using `Runtime.totalMemory` and `Runtime.maxMemory`. It showed that there was about 7 GB max memory available during the benchmark runs, and the program only used 400 MB to 1 GB. I then tried allocating a 4 GB array during the run to ensure that the memory was usable and it worked with no problem. Then looking at the "JSON serialization" results again, I saw that "vertx-web-kotlinx" performs a lot worse in this test too, and decided that this is more likely to be the bottleneck. Therefore, the static serializers are provided explicitly and the performance is improved slightly as tested on my machine. (Also, see commit 315b4e3 for an attempt before.) I then copied the "JSON serialization" test code from "vertx-web-kotlin-coroutines" and ran the benchmark to see if there were other factors, such as project configuration differences, affecting the performance, and the answer was no. On my machine, the "JSON serialization" performance of "vertx-web-kotlinx" is about 80% - 85% of that of "vertx-web-kotlin-coroutines". And I think the bottleneck possibly lies in kotlinx.serialization serializing an object to a byte array first and then copying it to a Vert.x buffer. Remove the broken tag in "vertx-web-kotlin-coroutines" BTW, which was added in commit e53e026, for the benchmark runs without problems now as I tested. * Update README.md correspondingly * Add `--no-daemon` to the Gradle command in the Dockerfiles * Update the "Connection reset" exception to the io_uring one that's ignored in logging * Use `encodeToBufferedSink` in "kotlinx-serialization-json-okio" with a custom-implemented `VertxBufferSink` in JSON serialization The "JSON serialization" performance is on par with using `io.vertx.core.json.Json.encodeToBuffer` as tested on my machine after this change. * Replace Okio with kotlinx-io and remove unneeded code The "JSON serialization" performance seems to be slightly less. * Rename 2 classes to clarify * Use to the new Vert.x coroutine APIs introduced in vert-x3/vertx-lang-kotlin#253 / vert-x3/vertx-lang-kotlin@e841975 There is no noticeable performance degradation in the "plaintext" and "JSON serialization" tests. * Simply the code introduced in the previous commit by making `MainVerticle` implement `CoroutineRouterSupport` I didn't go through [the docs](https://vertx.io/docs/vertx-lang-kotlin-coroutines/kotlin/#_vert_x_web) thoroughly before implementing this. * Revamp the "vertx-web-kotlin-coroutines" portion project too following the changes made to the "vertx-web-kotlinx" portion The "gradlew" script somehow had incorrect access permissions and is fixed by bumping the Gradle wrapper. To keep the dependencies consistent with the "vert-web" portion, some dependencies are not updated to the latest versions. Remove 2 useless `COPY`s in "vertx-web-kotlin-coroutines-postgres.dockerfile" BTW. * Remove unneeded and incorrect comments Wrapping something as a Vert.x `Buffer` by implementing the `Buffer` interface is not viable because `BufferImpl` contains casts from a `Buffer` to a `BufferImpl`.
1 parent de4bda3 commit fed744b

21 files changed

+231
-130
lines changed

frameworks/Kotlin/vertx-web-kotlin-coroutines/benchmark_config.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
"database_os": "Linux",
1919
"display_name": "vertx-web-kotlin-coroutines",
2020
"notes": "",
21-
"versus": "vertx-web",
22-
"tags": ["broken"]
21+
"versus": "vertx-web"
2322
},
2423
"postgres": {
2524
"db_url": "/db",

frameworks/Kotlin/vertx-web-kotlin-coroutines/build.gradle.kts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2-
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
3-
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
42

53
tasks.wrapper {
64
distributionType = Wrapper.DistributionType.ALL
75
}
86

97
plugins {
10-
kotlin("jvm") version "1.8.10"
8+
kotlin("jvm") version "2.0.21"
119
application
1210
id("nu.studer.rocker") version "3.0.4"
13-
id("com.github.johnrengelman.shadow") version "7.1.2"
11+
id("com.gradleup.shadow") version "8.3.4"
1412
}
1513

1614
group = "io.vertx"
17-
version = "4.3.8"
15+
version = "4.3.8" // 4.5.10 is available, but this is not updated to be kept consistent with the "vert-web" portion
1816

1917
repositories {
2018
mavenCentral()
2119
}
2220

2321
dependencies {
24-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
22+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
2523
implementation(platform("io.vertx:vertx-stack-depchain:$version"))
2624
implementation("io.vertx:vertx-core")
27-
implementation("com.fasterxml.jackson.module:jackson-module-blackbird:2.14.2")
25+
implementation("com.fasterxml.jackson.module:jackson-module-blackbird:2.14.2") // 2.18.1 is available, but this is not updated to be kept consistent with the "vert-web" portion
2826
implementation("io.vertx:vertx-web")
2927
implementation("io.vertx:vertx-pg-client")
3028
implementation("io.vertx:vertx-web-templ-rocker")
31-
implementation("io.netty", "netty-transport-native-epoll", classifier = "linux-x86_64")
29+
runtimeOnly("io.netty", "netty-transport-native-epoll", classifier = "linux-x86_64")
30+
// not used to make the project consistent with the "vert-web" portion
31+
/*
32+
runtimeOnly("io.vertx:vertx-io_uring-incubator")
33+
runtimeOnly("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.25.Final:linux-x86_64")
34+
*/
3235
implementation("io.vertx:vertx-lang-kotlin")
3336
implementation("io.vertx:vertx-lang-kotlin-coroutines")
3437
}
@@ -38,14 +41,12 @@ rocker {
3841
create("main") {
3942
templateDir.set(file("src/main/resources"))
4043
optimize.set(true)
41-
javaVersion.set("17")
44+
javaVersion.set("17") // kept consistent with the "vert-web" portion
4245
}
4346
}
4447
}
4548

46-
tasks.withType<KotlinCompile> {
47-
compilerOptions.jvmTarget.set(JvmTarget.JVM_17)
48-
}
49+
kotlin.jvmToolchain(17) // kept consistent with the "vert-web" portion
4950

5051

5152
// content below copied from the project generated by the app generator
Binary file not shown.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
44
networkTimeout=10000
5+
validateDistributionUrl=true
56
zipStoreBase=GRADLE_USER_HOME
67
zipStorePath=wrapper/dists

frameworks/Kotlin/vertx-web-kotlin-coroutines/gradlew

100644100755
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
1717
#
18+
# SPDX-License-Identifier: Apache-2.0
19+
#
1820

1921
##############################################################################
2022
#
@@ -55,7 +57,7 @@
5557
# Darwin, MinGW, and NonStop.
5658
#
5759
# (3) This script is generated from the Groovy template
58-
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
60+
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
5961
# within the Gradle project.
6062
#
6163
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -83,10 +85,9 @@ done
8385
# This is normally unused
8486
# shellcheck disable=SC2034
8587
APP_BASE_NAME=${0##*/}
86-
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87-
88-
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89-
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
88+
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89+
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
90+
' "$PWD" ) || exit
9091

9192
# Use the maximum available, or set MAX_FD != -1 to use that value.
9293
MAX_FD=maximum
@@ -133,26 +134,29 @@ location of your Java installation."
133134
fi
134135
else
135136
JAVACMD=java
136-
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137+
if ! command -v java >/dev/null 2>&1
138+
then
139+
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137140
138141
Please set the JAVA_HOME variable in your environment to match the
139142
location of your Java installation."
143+
fi
140144
fi
141145

142146
# Increase the maximum file descriptors if we can.
143147
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144148
case $MAX_FD in #(
145149
max*)
146150
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147-
# shellcheck disable=SC3045
151+
# shellcheck disable=SC2039,SC3045
148152
MAX_FD=$( ulimit -H -n ) ||
149153
warn "Could not query maximum file descriptor limit"
150154
esac
151155
case $MAX_FD in #(
152156
'' | soft) :;; #(
153157
*)
154158
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155-
# shellcheck disable=SC3045
159+
# shellcheck disable=SC2039,SC3045
156160
ulimit -n "$MAX_FD" ||
157161
warn "Could not set maximum file descriptor limit to $MAX_FD"
158162
esac
@@ -197,11 +201,15 @@ if "$cygwin" || "$msys" ; then
197201
done
198202
fi
199203

200-
# Collect all arguments for the java command;
201-
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202-
# shell script including quotes and variable substitutions, so put them in
203-
# double quotes to make sure that they get re-expanded; and
204-
# * put everything else in single quotes, so that it's not re-expanded.
204+
205+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
206+
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
207+
208+
# Collect all arguments for the java command:
209+
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
210+
# and any embedded shellness will be escaped.
211+
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
212+
# treated as '${Hostname}' itself on the command line.
205213

206214
set -- \
207215
"-Dorg.gradle.appname=$APP_BASE_NAME" \

frameworks/Kotlin/vertx-web-kotlin-coroutines/gradlew.bat

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
@rem See the License for the specific language governing permissions and
1414
@rem limitations under the License.
1515
@rem
16+
@rem SPDX-License-Identifier: Apache-2.0
17+
@rem
1618

1719
@if "%DEBUG%"=="" @echo off
1820
@rem ##########################################################################
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
4345
%JAVA_EXE% -version >NUL 2>&1
4446
if %ERRORLEVEL% equ 0 goto execute
4547

46-
echo.
47-
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48-
echo.
49-
echo Please set the JAVA_HOME variable in your environment to match the
50-
echo location of your Java installation.
48+
echo. 1>&2
49+
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50+
echo. 1>&2
51+
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52+
echo location of your Java installation. 1>&2
5153

5254
goto fail
5355

@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
5759

5860
if exist "%JAVA_EXE%" goto execute
5961

60-
echo.
61-
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62-
echo.
63-
echo Please set the JAVA_HOME variable in your environment to match the
64-
echo location of your Java installation.
62+
echo. 1>&2
63+
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64+
echo. 1>&2
65+
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66+
echo location of your Java installation. 1>&2
6567

6668
goto fail
6769

frameworks/Kotlin/vertx-web-kotlin-coroutines/vertx-web-kotlin-coroutines-postgres.dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
FROM gradle:7.6-jdk17 as gradle
1+
FROM gradle:8.10.2-jdk17 as gradle
22
WORKDIR /vertx-web-kotlin-coroutines
3-
COPY gradle gradle
43
COPY src src
54
COPY build.gradle.kts build.gradle.kts
65
COPY gradle.properties gradle.properties
7-
COPY gradlew gradlew
86
COPY settings.gradle.kts settings.gradle.kts
97
RUN gradle shadowJar
108

frameworks/Kotlin/vertx-web-kotlin-coroutines/vertx-web-kotlin-coroutines.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM gradle:7.6-jdk17 as gradle
1+
FROM gradle:8.10.2-jdk17 as gradle
22
WORKDIR /vertx-web-kotlin-coroutines
33
COPY src src
44
COPY build.gradle.kts build.gradle.kts

frameworks/Kotlin/vertx-web-kotlinx/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Vert.x-Web in Kotlin with request handling implemented as much with official kotlinx libraries as possible.
44

5-
Code is written from scratch to be as concise as possible with common code extracted into common (possibly inline) functions. SQL client implementation details and JVM Options are adapted referring to [the vertx-web portion](../../Java/vertx-web) and [the vertx portion](../../Java/vertx). All requests are handled in coroutines and suspend `await`s are used instead of future compositions. Compared to [the vertx-web-kotlin-coroutines portion](../vertx-web-kotlin-coroutines), besides adopting the Kotlinx libraries, this project simplifies the code by using more built-in Coroutine functions and avoids mutability as much as possible. JSON serialization is implemented with kotlinx.serialization and Fortunes with kotlinx.html. The benchmark is run on the latest LTS version of JVM, 17.
5+
Code is written from scratch to be as concise as possible with common code extracted into common (possibly inline) functions. SQL client implementation details and JVM Options are adapted referring to [the vertx-web portion](../../Java/vertx-web) and [the vertx portion](../../Java/vertx). All requests are handled in coroutines and suspend `await`s are used instead of future compositions. Compared to [the vertx-web-kotlin-coroutines portion](../vertx-web-kotlin-coroutines), besides adopting the Kotlinx libraries, this project simplifies the code by using more built-in Coroutine functions and avoids mutability as much as possible. JSON serialization is implemented with kotlinx.serialization and Fortunes with kotlinx.html. The benchmark is run on the latest LTS version of JVM, 21.
66

77
## Test Type Implementation Source Code
88

@@ -27,6 +27,7 @@ The tests were run with:
2727
* [Vert.x Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/)
2828
* [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines)
2929
* [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization)
30+
* [kotlinx-io](https://github.com/Kotlin/kotlinx-io)
3031
* [kotlinx.html](https://github.com/Kotlin/kotlinx.html)
3132

3233
## Test URLs
Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2-
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3-
41
tasks.wrapper {
52
distributionType = Wrapper.DistributionType.ALL
63
}
74

85
plugins {
9-
val kotlinVersion = "1.8.10"
6+
val kotlinVersion = "2.0.21"
107
kotlin("jvm") version kotlinVersion
118
kotlin("plugin.serialization") version kotlinVersion
129
application
@@ -16,23 +13,29 @@ repositories {
1613
mavenCentral()
1714
}
1815

19-
val vertxVersion = "4.3.8"
16+
val vertxVersion = "4.5.10"
17+
val kotlinxSerializationVersion = "1.7.3"
2018
dependencies {
2119
implementation(platform("io.vertx:vertx-stack-depchain:$vertxVersion"))
2220
implementation("io.vertx:vertx-web")
2321
implementation("io.vertx:vertx-pg-client")
2422
implementation("io.netty", "netty-transport-native-epoll", classifier = "linux-x86_64")
2523
implementation("io.vertx:vertx-lang-kotlin")
2624
implementation("io.vertx:vertx-lang-kotlin-coroutines")
25+
runtimeOnly("io.vertx:vertx-io_uring-incubator")
26+
// This dependency has to be added for io_uring to work.
27+
runtimeOnly("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.25.Final:linux-x86_64")
2728

28-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
29-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
30-
implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.0")
31-
//implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
32-
}
29+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
3330

34-
tasks.withType<KotlinCompile> {
35-
compilerOptions.jvmTarget.set(JvmTarget.JVM_17)
31+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
32+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-io:$kotlinxSerializationVersion")
33+
implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.5.4")
34+
35+
implementation("org.jetbrains.kotlinx:kotlinx-html:0.11.0")
36+
//implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") // the latest version is 0.6.1
3637
}
3738

39+
kotlin.jvmToolchain(21)
40+
3841
application.mainClass.set("MainKt")

0 commit comments

Comments
 (0)