From 3dbce5ab895a12d4004f88e86c7d7bc29454d98d Mon Sep 17 00:00:00 2001 From: Juanjo Aguililla Date: Thu, 8 Jun 2023 15:17:56 +0200 Subject: [PATCH] [Kotlin / Hexagon] Add asynchronous and native image benchmarks (#8250) * Fix error with URLs in JEE servers * Clean up * Avoid classpath URLs * Fix template loading error * Fix template loading error * Chores * Fix template loading error * Delete MongoDB DB support Storage support in Hexagon will be moved outside the Toolkit, and so, it will be left outside the benchmark. * Fix runtime problem * Update Hexagon version * Make Jackson Blackbird module optional * Add variation with Blackbird module enabled * Upgrade Hexagon version * Enable blackbird Jackson module by default * Update dependencies * Use Hexagon version 2.0.0-B1 (and a little cleanup) * Use Hexagon version 2.0.0-B1 (and a little cleanup) * Use Tomcat instead Resin to test JEE integration * Remove unused environment variable * Clean Tomcat dockerfile * Minor improvements * Minor improvements * Update to release version * Update to the latest Hexagon release * Add Netty adapter test * Remove Gradle Wrapper * Update version * Update version * Minimize template * Skip Hexagon checks in the container * Add Netty Epoll benchmark * Database and template improvements * Update Hexagon version * Update Hexagon version * Update DB settings * Use a single store and template engine to simplify benchmark * Bump mysql-connector-java in /frameworks/Java/wicket Bumps [mysql-connector-java](https://github.com/mysql/mysql-connector-j) from 8.0.27 to 8.0.28. - [Release notes](https://github.com/mysql/mysql-connector-j/releases) - [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/8.0/CHANGES) - [Commits](https://github.com/mysql/mysql-connector-j/compare/8.0.27...8.0.28) --- updated-dependencies: - dependency-name: mysql:mysql-connector-java dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump mongodb-driver-sync from 4.2.0 to 4.2.1 in /frameworks/Java/javalin Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.2.0...r4.2.1) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/starlette Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/django Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/routerling Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/japronto Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/fastapi Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/uvicorn Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.2.0 to 5.4.0 in /frameworks/Python/flask Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.2.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump ujson from 5.1 to 5.4.0 in /frameworks/Python/aiohttp Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.1 to 5.4.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.1.0...5.4.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump rails-html-sanitizer from 1.4.2 to 1.4.3 in /frameworks/Ruby/rails Bumps [rails-html-sanitizer](https://github.com/rails/rails-html-sanitizer) from 1.4.2 to 1.4.3. - [Release notes](https://github.com/rails/rails-html-sanitizer/releases) - [Changelog](https://github.com/rails/rails-html-sanitizer/blob/master/CHANGELOG.md) - [Commits](https://github.com/rails/rails-html-sanitizer/compare/v1.4.2...v1.4.3) --- updated-dependencies: - dependency-name: rails-html-sanitizer dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump jetty-server in /frameworks/Java/jetty Bumps [jetty-server](https://github.com/eclipse/jetty.project) from 9.4.41.v20210516 to 10.0.10. - [Release notes](https://github.com/eclipse/jetty.project/releases) - [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.41.v20210516...jetty-10.0.10) --- updated-dependencies: - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump undertow-core in /frameworks/Java/undertow Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.2.11.Final to 2.2.15.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.2.11.Final...2.2.15.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Update versions * Update README.md * Bump sanic from 22.3.1 to 22.6.1 in /frameworks/Python/sanic Bumps [sanic](https://github.com/sanic-org/sanic) from 22.3.1 to 22.6.1. - [Release notes](https://github.com/sanic-org/sanic/releases) - [Changelog](https://github.com/sanic-org/sanic/blob/main/CHANGELOG.rst) - [Commits](https://github.com/sanic-org/sanic/compare/v22.3.1...v22.6.1) --- updated-dependencies: - dependency-name: sanic dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/light-java Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/rapidoid Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/jooby Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/servlet Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/spring-webflux Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/smart-socket Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/act Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Kotlin/kooby Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/dropwizard Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.3.3 to 42.4.1 in /frameworks/Java/hserver Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.4.0 to 42.4.1 in /frameworks/Java/undertow Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.4.0 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.4.0...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump postgresql from 42.2.23 to 42.4.1 in /frameworks/Kotlin/ktor/ktor Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.2.23 to 42.4.1. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.2.23...REL42.4.1) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Update dependencies * Bump undertow-core in /frameworks/Java/light-java Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.2.15.Final to 2.2.19.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.2.15.Final...2.2.19.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Bump undertow-core in /frameworks/Java/undertow Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.2.18.Final to 2.2.19.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.2.18.Final...2.2.19.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Delete Gradle Wrapper * Use different JSON serializer * Restore non Hexagon files * Update Hexagon version * Run pipeline * Run pipeline * Bump axum-core from 0.2.7 to 0.2.8 in /frameworks/Rust/axum Bumps [axum-core](https://github.com/tokio-rs/axum) from 0.2.7 to 0.2.8. - [Release notes](https://github.com/tokio-rs/axum/releases) - [Changelog](https://github.com/tokio-rs/axum/blob/main/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/axum/compare/axum-core-v0.2.7...axum-core-v0.2.8) --- updated-dependencies: - dependency-name: axum-core dependency-type: indirect ... Signed-off-by: dependabot[bot] * Revert "Bump axum-core from 0.2.7 to 0.2.8 in /frameworks/Rust/axum" This reverts commit 4422de8915e70cdca67a07c2e0fdb0610757924b. * Version updates, code refactor and new benchmark cases * Version updates * Version updates * Version updates * [Hexagon] Refactor and updates: * Update Hexagon version * Use Rocker template * Modularize the different scenarios * Fix connection problems * Update Hexagon * Update Gradle * Update dependencies * Update Hexagon version * Update Gradle Wrapper * Add async and native support * Add async and native support * Add async and native support --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- frameworks/Kotlin/hexagon/.dockerignore | 2 + .../Kotlin/hexagon/benchmark_config.json | 69 +++++++++ frameworks/Kotlin/hexagon/build.gradle | 19 ++- frameworks/Kotlin/hexagon/config.toml | 54 +++++++ frameworks/Kotlin/hexagon/core/build.gradle | 9 +- .../core/src/main/kotlin/Controller.kt | 24 ++-- .../core/native-image.properties | 7 + .../core/reflect-config.json | 23 +++ .../src/main/resources/fortunes.pebble.html | 21 --- .../Kotlin/hexagon/core_async/build.gradle | 32 +++++ .../core_async/src/main/kotlin/Benchmark.kt | 28 ++++ .../core_async/src/main/kotlin/Controller.kt | 133 ++++++++++++++++++ .../src/main/kotlin/store/BenchmarkStore.kt | 34 +++++ .../core/native-image.properties | 7 + .../core/reflect-config.json | 23 +++ .../src/main/resources/fortunes.rocker.html | 24 ++++ .../hexagon/gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 62076 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- frameworks/Kotlin/hexagon/gradlew | 11 +- .../hexagon/hexagon-jetty-native.dockerfile | 21 +++ .../hexagon-jettyloom-pgclient.dockerfile | 15 +- .../hexagon/hexagon-jettyloom.dockerfile | 15 +- .../hexagon-netty-async-pgclient.dockerfile | 23 +++ .../hexagon/hexagon-netty-native.dockerfile | 21 +++ .../Kotlin/hexagon/hexagon-netty.dockerfile | 15 +- .../hexagon-nettyepoll-pgclient.dockerfile | 15 +- .../hexagon/hexagon-nettyepoll.dockerfile | 15 +- .../Kotlin/hexagon/hexagon-tomcat.dockerfile | 12 +- .../hexagon/hexagon-vertx-pgclient.dockerfile | 23 +++ frameworks/Kotlin/hexagon/hexagon.dockerfile | 15 +- .../hexagon_jetty_pgclient/build.gradle | 6 - .../hexagon_jetty_postgresql/build.gradle | 7 +- .../hexagon_netty_async_pgclient/build.gradle | 7 + .../src/main/kotlin/Benchmark.kt | 25 ++++ .../hexagon_netty_postgresql/build.gradle | 7 +- .../src/main/kotlin/Benchmark.kt | 7 + .../hexagon_nettyepoll_pgclient/build.gradle | 6 - .../src/main/kotlin/Benchmark.kt | 7 + .../build.gradle | 6 - .../src/main/kotlin/Benchmark.kt | 7 + .../src/main/kotlin/WebListenerServer.kt | 4 +- .../hexagon_vertx_pgclient/build.gradle | 9 ++ .../src/main/kotlin/Benchmark.kt | 33 +++++ frameworks/Kotlin/hexagon/model/build.gradle | 4 + .../src/main/kotlin/Settings.kt | 0 .../src/main/kotlin/model/CachedWorld.kt | 0 .../src/main/kotlin/model/Fortune.kt | 0 .../src/main/kotlin/model/Message.kt | 0 .../src/main/kotlin/model/World.kt | 0 frameworks/Kotlin/hexagon/settings.gradle | 5 + .../src/main/kotlin/BenchmarkPgClientStore.kt | 2 +- .../hexagon/store_pgclient_async/build.gradle | 6 + .../src/main/kotlin/BenchmarkPgClientStore.kt | 114 +++++++++++++++ .../src/main/kotlin/BenchmarkSqlStore.kt | 2 +- 54 files changed, 837 insertions(+), 139 deletions(-) create mode 100644 frameworks/Kotlin/hexagon/.dockerignore create mode 100644 frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties create mode 100644 frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json delete mode 100644 frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.pebble.html create mode 100644 frameworks/Kotlin/hexagon/core_async/build.gradle create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Benchmark.kt create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Controller.kt create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/kotlin/store/BenchmarkStore.kt create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json create mode 100644 frameworks/Kotlin/hexagon/core_async/src/main/resources/fortunes.rocker.html create mode 100644 frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile create mode 100644 frameworks/Kotlin/hexagon/hexagon-netty-async-pgclient.dockerfile create mode 100644 frameworks/Kotlin/hexagon/hexagon-netty-native.dockerfile create mode 100644 frameworks/Kotlin/hexagon/hexagon-vertx-pgclient.dockerfile create mode 100644 frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/build.gradle create mode 100644 frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/src/main/kotlin/Benchmark.kt create mode 100644 frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/build.gradle create mode 100644 frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/src/main/kotlin/Benchmark.kt create mode 100644 frameworks/Kotlin/hexagon/model/build.gradle rename frameworks/Kotlin/hexagon/{core => model}/src/main/kotlin/Settings.kt (100%) rename frameworks/Kotlin/hexagon/{core => model}/src/main/kotlin/model/CachedWorld.kt (100%) rename frameworks/Kotlin/hexagon/{core => model}/src/main/kotlin/model/Fortune.kt (100%) rename frameworks/Kotlin/hexagon/{core => model}/src/main/kotlin/model/Message.kt (100%) rename frameworks/Kotlin/hexagon/{core => model}/src/main/kotlin/model/World.kt (100%) create mode 100644 frameworks/Kotlin/hexagon/store_pgclient_async/build.gradle create mode 100644 frameworks/Kotlin/hexagon/store_pgclient_async/src/main/kotlin/BenchmarkPgClientStore.kt diff --git a/frameworks/Kotlin/hexagon/.dockerignore b/frameworks/Kotlin/hexagon/.dockerignore new file mode 100644 index 00000000000..5b154f2de67 --- /dev/null +++ b/frameworks/Kotlin/hexagon/.dockerignore @@ -0,0 +1,2 @@ + +**/build/ diff --git a/frameworks/Kotlin/hexagon/benchmark_config.json b/frameworks/Kotlin/hexagon/benchmark_config.json index 4bcc8b23f66..d5134ade6c8 100644 --- a/frameworks/Kotlin/hexagon/benchmark_config.json +++ b/frameworks/Kotlin/hexagon/benchmark_config.json @@ -136,6 +136,75 @@ "notes": "http://hexagonkt.com", "versus": "netty" }, + "netty-native": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/query?queries=", + "fortune_url": "/fortunes", + "update_url": "/update?queries=", + "cached_query_url": "/cached-queries?count=", + "plaintext_url": "/plaintext", + "port": 9090, + "approach": "Realistic", + "classification": "Micro", + "database": "postgres", + "framework": "Hexagon", + "language": "Kotlin", + "orm": "Raw", + "platform": "Netty", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Hexagon Netty Native PostgreSQL", + "notes": "http://hexagonkt.com", + "versus": "netty" + }, + "netty-async-pgclient": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/query?queries=", + "fortune_url": "/fortunes", + "update_url": "/update?queries=", + "cached_query_url": "/cached-queries?count=", + "plaintext_url": "/plaintext", + "port": 9090, + "approach": "Realistic", + "classification": "Micro", + "database": "postgres", + "framework": "Hexagon", + "language": "Kotlin", + "orm": "Raw", + "platform": "Netty", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Hexagon Netty Async PgClient", + "notes": "http://hexagonkt.com", + "versus": "netty" + }, + "vertx-pgclient": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/query?queries=", + "fortune_url": "/fortunes", + "update_url": "/update?queries=", + "cached_query_url": "/cached-queries?count=", + "plaintext_url": "/plaintext", + "port": 9090, + "approach": "Realistic", + "classification": "Micro", + "database": "postgres", + "framework": "Hexagon", + "language": "Kotlin", + "orm": "Raw", + "platform": "Vertx", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Hexagon Vertx PgClient", + "notes": "http://hexagonkt.com", + "versus": "vertx" + }, "tomcat": { "json_url": "/json", "db_url": "/db", diff --git a/frameworks/Kotlin/hexagon/build.gradle b/frameworks/Kotlin/hexagon/build.gradle index 4aad4ab8f98..755096930bc 100644 --- a/frameworks/Kotlin/hexagon/build.gradle +++ b/frameworks/Kotlin/hexagon/build.gradle @@ -1,6 +1,7 @@ plugins { - id "org.jetbrains.kotlin.jvm" version "1.8.10" apply false + id "org.jetbrains.kotlin.jvm" version "1.8.21" apply false + id "org.graalvm.buildtools.native" version "0.9.22" apply false } version = "1.0.0" @@ -8,19 +9,23 @@ description = "TFB benchmark" group = "com.hexagonkt" ext { - hexagonVersion = "2.6.6" + hexagonVersion = "3.0.0-B1" + jettyVersion = "11.0.15" + nettyVersion = "4.1.93.Final" + hikariVersion = "5.0.1" - jettyVersion = "11.0.14" postgresqlVersion = "42.6.0" - vertxVersion = "4.4.0" + vertxVersion = "4.4.2" cache2kVersion = "2.6.1.Final" - nettyVersion = "4.1.90.Final" + applicationClass = "com.hexagonkt.BenchmarkKt" + modules = "java.naming,java.sql,java.management" + options = "--enable-preview" gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/$hexagonVersion/gradle" } -defaultTasks("build") - subprojects { + version = rootProject.version + apply(from: "$gradleScripts/kotlin.gradle") } diff --git a/frameworks/Kotlin/hexagon/config.toml b/frameworks/Kotlin/hexagon/config.toml index d51d0e8ccf6..baeb6ac78ad 100644 --- a/frameworks/Kotlin/hexagon/config.toml +++ b/frameworks/Kotlin/hexagon/config.toml @@ -73,6 +73,24 @@ platform = "Netty" webserver = "None" versus = "netty" +[netty-native] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/query?queries=" +urls.update = "/update?queries=" +urls.fortune = "/fortunes" +urls.cached_query = "/cached-queries?count=" +approach = "Realistic" +classification = "Micro" +database = "postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "Netty" +webserver = "None" +versus = "netty" + [nettyepoll] urls.plaintext = "/plaintext" urls.json = "/json" @@ -109,6 +127,24 @@ platform = "Netty" webserver = "None" versus = "netty" +[nettyepoll-async-pgclient] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/query?queries=" +urls.update = "/update?queries=" +urls.fortune = "/fortunes" +urls.cached_query = "/cached-queries?count=" +approach = "Realistic" +classification = "Micro" +database = "postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "Netty" +webserver = "None" +versus = "netty" + [tomcat] urls.plaintext = "/plaintext" urls.json = "/json" @@ -126,3 +162,21 @@ orm = "Raw" platform = "Servlet" webserver = "Tomcat" versus = "servlet" + +[vertx-pgclient] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/query?queries=" +urls.update = "/update?queries=" +urls.fortune = "/fortunes" +urls.cached_query = "/cached-queries?count=" +approach = "Realistic" +classification = "Micro" +database = "postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "Vertx" +webserver = "None" +versus = "vertx" diff --git a/frameworks/Kotlin/hexagon/core/build.gradle b/frameworks/Kotlin/hexagon/core/build.gradle index af7552398d3..4cf6f44b80c 100644 --- a/frameworks/Kotlin/hexagon/core/build.gradle +++ b/frameworks/Kotlin/hexagon/core/build.gradle @@ -4,6 +4,7 @@ plugins { } dependencies { + api(project(":model")) api("com.hexagonkt:http_server:$hexagonVersion") api("com.hexagonkt:templates_rocker:$hexagonVersion") api("com.hexagonkt:logging_slf4j_jul:$hexagonVersion") @@ -13,11 +14,9 @@ dependencies { tasks.register("minimizeTemplate") { doLast { - [ "fortunes.pebble.html", "fortunes.rocker.html" ].forEach { t -> - File template = file("$buildDir/resources/main/$t") - List lines = template.readLines().collect { it.trim() } - template.write(lines.join("")) - } + File template = file("$buildDir/resources/main/fortunes.rocker.html") + List lines = template.readLines().collect { it.trim() } + template.write(lines.join("")) } } diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/Controller.kt b/frameworks/Kotlin/hexagon/core/src/main/kotlin/Controller.kt index b4714a76049..37ab786e791 100644 --- a/frameworks/Kotlin/hexagon/core/src/main/kotlin/Controller.kt +++ b/frameworks/Kotlin/hexagon/core/src/main/kotlin/Controller.kt @@ -8,9 +8,9 @@ import com.hexagonkt.http.model.ContentType import com.hexagonkt.http.model.Header import com.hexagonkt.http.model.Headers import com.hexagonkt.http.server.callbacks.DateCallback -import com.hexagonkt.http.server.handlers.HttpServerContext -import com.hexagonkt.http.server.handlers.PathHandler -import com.hexagonkt.http.server.handlers.path +import com.hexagonkt.http.handlers.HttpContext +import com.hexagonkt.http.handlers.PathHandler +import com.hexagonkt.http.handlers.path import com.hexagonkt.model.* import com.hexagonkt.serialization.jackson.json.Json import com.hexagonkt.serialization.serialize @@ -55,9 +55,9 @@ class Controller( private fun Message.toJson(): String = toMap().serialize(Json.raw) - private fun HttpServerContext.listFortunes( + private fun HttpContext.listFortunes( store: BenchmarkStore, templateUrl: URL, templateAdapter: TemplatePort - ): HttpServerContext { + ): HttpContext { val fortunes = store.findAllFortunes() + Fortune(0, "Additional fortune added at request time.") val sortedFortunes = fortunes.sortedBy { it.message } @@ -67,7 +67,7 @@ class Controller( return ok(body, contentType = html) } - private fun HttpServerContext.dbQuery(store: BenchmarkStore): HttpServerContext { + private fun HttpContext.dbQuery(store: BenchmarkStore): HttpContext { val ids = listOf(randomWorld()) val worlds = store.findWorlds(ids) val world = worlds.first().toMap() @@ -75,7 +75,7 @@ class Controller( return sendJson(world) } - private fun HttpServerContext.getWorlds(store: BenchmarkStore): HttpServerContext { + private fun HttpContext.getWorlds(store: BenchmarkStore): HttpContext { val worldsCount = getWorldsCount(queriesParam) val ids = (1..worldsCount).map { randomWorld() } val worlds = store.findWorlds(ids).map { it.toMap() } @@ -83,7 +83,7 @@ class Controller( return sendJson(worlds) } - private fun HttpServerContext.getCachedWorlds(store: BenchmarkStore): HttpServerContext { + private fun HttpContext.getCachedWorlds(store: BenchmarkStore): HttpContext { val worldsCount = getWorldsCount(cachedQueriesParam) val ids = (1..worldsCount).map { randomWorld() } val worlds = store.findCachedWorlds(ids).map { it.toMap() } @@ -91,7 +91,7 @@ class Controller( return sendJson(worlds) } - private fun HttpServerContext.updateWorlds(store: BenchmarkStore): HttpServerContext { + private fun HttpContext.updateWorlds(store: BenchmarkStore): HttpContext { val worldsCount = getWorldsCount(queriesParam) val worlds = (1..worldsCount).map { World(randomWorld(), randomWorld()) } @@ -100,11 +100,11 @@ class Controller( return sendJson(worlds.map { it.toMap() }) } - private fun HttpServerContext.sendJson(body: Any): HttpServerContext = + private fun HttpContext.sendJson(body: Any): HttpContext = ok(body.serialize(Json.raw), contentType = json) - private fun HttpServerContext.getWorldsCount(parameter: String): Int = - request.queryParameters[parameter]?.value?.toIntOrNull().let { + private fun HttpContext.getWorldsCount(parameter: String): Int = + request.queryParameters[parameter]?.string()?.toIntOrNull().let { when { it == null -> 1 it < 1 -> 1 diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties new file mode 100644 index 00000000000..ee1c0199d95 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties @@ -0,0 +1,7 @@ +Args= \ + -H:IncludeResources=.*\\.(html|class) \ + --enable-preview \ + --static \ + --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter \ + --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter$1 \ + --initialize-at-build-time=org.slf4j.LoggerFactory diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json new file mode 100644 index 00000000000..11815306be2 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json @@ -0,0 +1,23 @@ +[ + { + "name": "fortunes", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "fortunes$Template", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "fortunes$PlainText", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + } +] diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.pebble.html b/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.pebble.html deleted file mode 100644 index 1a74dd9800c..00000000000 --- a/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.pebble.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Fortunes - - - - - - - - {% for fortune in fortunes %} - - - - - {% endfor %} -
idmessage
{{ fortune.id }}{{ fortune.message }}
- - diff --git a/frameworks/Kotlin/hexagon/core_async/build.gradle b/frameworks/Kotlin/hexagon/core_async/build.gradle new file mode 100644 index 00000000000..0a33387738e --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/build.gradle @@ -0,0 +1,32 @@ + +plugins { + id("nu.studer.rocker") version("3.0.4") +} + +dependencies { + api(project(":model")) + api("com.hexagonkt:http_server_async:$hexagonVersion") + api("com.hexagonkt:templates_rocker:$hexagonVersion") + api("com.hexagonkt:logging_slf4j_jul:$hexagonVersion") + api("com.hexagonkt:serialization_jackson_json:$hexagonVersion") + api("org.cache2k:cache2k-core:$cache2kVersion") +} + +tasks.register("minimizeTemplate") { + doLast { + File template = file("$buildDir/resources/main/fortunes.rocker.html") + List lines = template.readLines().collect { it.trim() } + template.write(lines.join("")) + } +} + +jar.dependsOn("minimizeTemplate") + +rocker { + configurations { + create("main") { + templateDir.set(file("src/main/resources")) + optimize.set(true) + } + } +} diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Benchmark.kt new file mode 100644 index 00000000000..2bda28da73e --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Benchmark.kt @@ -0,0 +1,28 @@ +package com.hexagonkt.async + +import com.hexagonkt.Settings +import com.hexagonkt.http.server.async.HttpServer +import com.hexagonkt.http.server.async.HttpServerPort +import com.hexagonkt.http.server.async.HttpServerSettings +import com.hexagonkt.async.store.BenchmarkStore +import com.hexagonkt.templates.TemplatePort +import java.net.InetAddress +import java.net.URL + +class Benchmark( + private val engine: HttpServerPort, + private val store: BenchmarkStore, + private val template: TemplatePort, + private val templateUrl: URL, + private val settings: Settings = Settings(), +) { + val server: HttpServer by lazy { + val controller = Controller(settings, store, template, templateUrl) + val serverSettings = HttpServerSettings( + bindAddress = InetAddress.getByName(settings.bindAddress), + bindPort = settings.bindPort, + ) + + HttpServer(engine, controller.path, serverSettings) + } +} diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Controller.kt b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Controller.kt new file mode 100644 index 00000000000..683d39f4ffa --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/Controller.kt @@ -0,0 +1,133 @@ +package com.hexagonkt.async + +import com.hexagonkt.Settings +import com.hexagonkt.core.fieldsMapOf +import com.hexagonkt.core.media.APPLICATION_JSON +import com.hexagonkt.core.media.TEXT_HTML +import com.hexagonkt.core.media.TEXT_PLAIN +import com.hexagonkt.handlers.async.done +import com.hexagonkt.http.model.ContentType +import com.hexagonkt.http.model.Header +import com.hexagonkt.http.model.Headers +import com.hexagonkt.http.server.async.callbacks.DateCallback +import com.hexagonkt.http.handlers.async.HttpContext +import com.hexagonkt.http.handlers.async.PathHandler +import com.hexagonkt.http.handlers.async.path +import com.hexagonkt.model.* +import com.hexagonkt.serialization.jackson.json.Json +import com.hexagonkt.serialization.serialize +import com.hexagonkt.async.store.BenchmarkStore +import com.hexagonkt.templates.TemplatePort +import java.net.URL +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ThreadLocalRandom +import kotlin.text.Charsets.UTF_8 + +class Controller( + settings: Settings, + store: BenchmarkStore, + templateEngine: TemplatePort, + templateUrl: URL, +) { + private val queriesParam: String = settings.queriesParam + private val cachedQueriesParam: String = settings.cachedQueriesParam + private val worldRows: Int = settings.worldRows + private val textMessage: String = settings.textMessage + + private val plain: ContentType = ContentType(TEXT_PLAIN) + private val json: ContentType = ContentType(APPLICATION_JSON) + private val html: ContentType = ContentType(TEXT_HTML, charset = UTF_8) + + private val headers = Headers(Header("server", "Hexagon")) + + val path: PathHandler by lazy { + path { + on("*") { send(headers = headers).done() } + on("*", DateCallback()) + + get("/plaintext") { ok(textMessage, contentType = plain).done() } + get("/json") { ok(Message(textMessage).toJson(), contentType = json).done() } + get("/fortunes") { listFortunes(store, templateUrl, templateEngine) } + get("/db") { dbQuery(store) } + get("/query") { getWorlds(store) } + get("/cached-queries") { getCachedWorlds(store) } + get("/update") { updateWorlds(store) } + } + } + + private fun Message.toJson(): String = + toMap().serialize(Json.raw) + + private fun HttpContext.listFortunes( + store: BenchmarkStore, templateUrl: URL, templateAdapter: TemplatePort + ): CompletableFuture = + store + .findAllFortunes() + .thenApply { it + Fortune(0, "Additional fortune added at request time.") } + .thenApply { fortunes -> fortunes.sortedBy { it.message } } + .thenApply { sortedFortunes -> mapOf("fortunes" to sortedFortunes) } + .thenApply { context -> templateAdapter.render(templateUrl, context) } + .thenApply { body -> ok(body, contentType = html) } + + private fun HttpContext.dbQuery(store: BenchmarkStore): CompletableFuture { + val ids = listOf(randomWorld()) + return store.findWorlds(ids) + .thenApply { worlds -> worlds.first().toMap()} + .thenApply { world -> sendJson(world) } + } + + private fun HttpContext.getWorlds(store: BenchmarkStore): CompletableFuture { + val worldsCount = getWorldsCount(queriesParam) + val ids = (1..worldsCount).map { randomWorld() } + return store.findWorlds(ids) + .thenApply { worlds -> worlds.map { it.toMap() } } + .thenApply { worlds -> sendJson(worlds) } + } + + private fun HttpContext.getCachedWorlds(store: BenchmarkStore): CompletableFuture { + val worldsCount = getWorldsCount(cachedQueriesParam) + val ids = (1..worldsCount).map { randomWorld() } + val worlds = store.findCachedWorlds(ids).map { it.toMap() } + + return sendJson(worlds).done() + } + + private fun HttpContext.updateWorlds(store: BenchmarkStore): CompletableFuture { + val worldsCount = getWorldsCount(queriesParam) + val worlds = (1..worldsCount).map { World(randomWorld(), randomWorld()) } + + return store.replaceWorlds(worlds) + .thenApply { sendJson(worlds.map { it.toMap() }) } + } + + private fun HttpContext.sendJson(body: Any): HttpContext = + ok(body.serialize(Json.raw), contentType = json) + + private fun HttpContext.getWorldsCount(parameter: String): Int = + request.queryParameters[parameter]?.string()?.toIntOrNull().let { + when { + it == null -> 1 + it < 1 -> 1 + it > 500 -> 500 + else -> it + } + } + + private fun randomWorld(): Int = + ThreadLocalRandom.current().nextInt(worldRows) + 1 + + private fun Message.toMap(): Map = + fieldsMapOf(Message::message to message) + + private fun World.toMap(): Map = + fieldsMapOf( + World::id to id, + World::randomNumber to randomNumber, + ) + + private fun CachedWorld.toMap(): Map = + fieldsMapOf( + CachedWorld::id to id, + CachedWorld::randomNumber to randomNumber, + ) +} diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/store/BenchmarkStore.kt b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/store/BenchmarkStore.kt new file mode 100644 index 00000000000..13f5aae7108 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/kotlin/store/BenchmarkStore.kt @@ -0,0 +1,34 @@ +package com.hexagonkt.async.store + +import com.hexagonkt.model.CachedWorld +import com.hexagonkt.model.Fortune +import com.hexagonkt.Settings +import com.hexagonkt.model.World +import org.cache2k.Cache +import org.cache2k.Cache2kBuilder +import java.util.concurrent.CompletableFuture + +abstract class BenchmarkStore(settings: Settings) { + + abstract fun findAllFortunes(): CompletableFuture> + abstract fun findWorlds(ids: List): CompletableFuture> + abstract fun replaceWorlds(worlds: List): CompletableFuture<*> + abstract fun initWorldsCache(cache: Cache) + abstract fun loadCachedWorld(id: Int): CachedWorld + abstract fun close() + + private val worldsCache: Cache by lazy { + object : Cache2kBuilder() {} + .eternal(true) + .disableMonitoring(true) + .disableStatistics(true) + .entryCapacity(settings.worldRows.toLong()) + .loader { id -> loadCachedWorld(id) } + .build() + .apply { initWorldsCache(this) } + } + + fun findCachedWorlds(ids: List): List { + return ids.mapNotNull { worldsCache.get(it) } + } +} diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties b/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties new file mode 100644 index 00000000000..ee1c0199d95 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties @@ -0,0 +1,7 @@ +Args= \ + -H:IncludeResources=.*\\.(html|class) \ + --enable-preview \ + --static \ + --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter \ + --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter$1 \ + --initialize-at-build-time=org.slf4j.LoggerFactory diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json b/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json new file mode 100644 index 00000000000..11815306be2 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json @@ -0,0 +1,23 @@ +[ + { + "name": "fortunes", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "fortunes$Template", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "fortunes$PlainText", + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + } +] diff --git a/frameworks/Kotlin/hexagon/core_async/src/main/resources/fortunes.rocker.html b/frameworks/Kotlin/hexagon/core_async/src/main/resources/fortunes.rocker.html new file mode 100644 index 00000000000..c9a9d4037e5 --- /dev/null +++ b/frameworks/Kotlin/hexagon/core_async/src/main/resources/fortunes.rocker.html @@ -0,0 +1,24 @@ +@import java.util.* +@import com.hexagonkt.model.Fortune +@args(Map context) + + + + + Fortunes + + + + + + + + @for ((fortune) : (Collection)context.get("fortunes")) { + + + + + } +
idmessage
@fortune.getId()@fortune.getMessage()
+ + diff --git a/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 13895 zcmZ8|Wmp``)-~=Hdu)0n3Y-8OvyK$p9^s9MM|Aj$miotNhy-{udLczZyd9uWtD)X_{|!LhIEF9y8(e*Z zW>^w$u&x|i9OjL=#6Nl~*ERulzX>8C-}o;iSMRYdfCU5d`~U{V4>HCg0HG4Xg2uP;fn!>S9+>LbuWbc0bETMQfo9~h}yI*TSv;Oikl~t-+xqI-`P$Rj@yi{mr2zC~s1snMT3!OPBdJ%IDnPXq+pl*Z>=+?qo${lkCSKmwTlVjfb3thU6B8yFjr!tphOs*G6 zwL`RyVAUXj4p=9&@PpWK)m+REuvHaq838TEhY^7W+JAp$ zZ^y;8`Z*@VqJ{sFFj?<|7SKS@G`$Yi)gx%nOi@Lr zCv0IJlFz0bP(eDIW(uWNq?;8zEAb+uGgnkLk;y!4XhA6=Eoa<`+|;6mOq>z`%ir@z$4)Mkd3 zF=hFo zyd{*bRQ4YUe^bU*Y`__)Uhu5NIjVJ~a}{lHp-_7wI?#EB11XcqmdY>pk`JJ) zW9Rt!tK=N>fZ!UDomwMnb`0EOvTjcNl=yW@$c!OAg*=l()GjZwSyJ+o^;Zi#I5*uP z$6qeih8&g8E(pNSneK>93A(8*%gvwv!0V|SqGcj55Y7`=N*@pJx_ig3uVuf-G~LJbm`7nxNcZ>Jgqy(LTHu_C2e>STp^Pm{}f&^)XU}vzuU`UV&>e& zqsXNXSs;Wri|?NhCq0vXC5$>9Cag$adyWz^x@NCiy2${9Dc)Y;J8k1Z933W$3$H}g zCQFU1XwzGm_WUheXvnDisH_%BdzMgNwk2^mHcQu*x>U%iN*B^8U(eVz1~(%`kV1Vb z=9T0xmN?bQMyrrd?u}jer}zV&sCK6zSm!zV8A8dP6THF=4*V{_K*E*K<)I(Q^(eV!m!vu##-2g|G z{RB;{gJB_X-w{ANq?ft_n!@=O8_gj6FxW&zO$7L3@NjWt@R{NxMbpHLk6;=2$0P5P=kKc1_85inX z#s$&s0zhV1cz>nRb#|D#N8Z-=Tphm)sGH>9cz3K3I)6XpimJW0(6$GtLzN(YPu9%R zdFXG9|30AZME4r@joC0IdvBBe08mF@+5Dd97p$h=n|pi80Cn2n{ev!S$llPGLqHva zZ3*OmW%!Qj>C$F!Ffafl7#I_1(gz!aa)b{ebU*=yH%^kr=~N?|2&2Df2o9X=2B?U!#R#+Cj45=f@=EcQx+9J z=X3~A=zbX29Fqn23m3dm}0Voj^Q9BjI=MiG+NZ)YCYn@r^qv(xE3=)&i z=(ML301=rNTptvUt2tnsPb1~G*DWFWoZfv)wV|uNW%?!)jju`jN(K-0$JYi!ofNup z9K%_ucHwutbZsl~vDQ!Jtj8uI6WA6K--@?8+_=t>g|kgUeC=w`IP9m&*fuoO3#A;t z&3@=3;J0>yjM89?h5MG$S`wW+=vyYOWQGhIP`^vScM8^JL{mGan5uTJPvAg$0z}8; z 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 J*WbtZ{{Z#P!zlm& delta 13442 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 diff --git a/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties index f0ae57febc4..ed4fda0fcea 100644 --- a/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-8.0.2-bin.zip +distributionUrl=https://services.gradle.org/distributions/gradle-8.1.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/frameworks/Kotlin/hexagon/gradlew b/frameworks/Kotlin/hexagon/gradlew index 65dcd68d65c..aeb74cbb43e 100755 --- a/frameworks/Kotlin/hexagon/gradlew +++ b/frameworks/Kotlin/hexagon/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile new file mode 100644 index 00000000000..223aae81894 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile @@ -0,0 +1,21 @@ +# +# BUILD +# +FROM ghcr.io/graalvm/native-image:ol9-java17-22.3.2 as build +USER root +WORKDIR /hexagon + +ADD . . +RUN microdnf -y install findutils +RUN ./gradlew --quiet classes +RUN ./gradlew --quiet -x test nativeCompile + +# +# RUNTIME +# +FROM scratch +ARG PROJECT=hexagon_jetty_postgresql + +COPY --from=build /hexagon/$PROJECT/build/native/nativeCompile/$PROJECT / + +ENTRYPOINT [ "/hexagon_jetty_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile index f047e7e599b..804555dae57 100644 --- a/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:19-jre-alpine +FROM docker.io/eclipse-temurin:20-jre-alpine +ARG PROJECT=hexagon_jetty_pgclient + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_jetty_pgclient ENV JDK_JAVA_OPTIONS --enable-preview -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA -DvirtualThreads=true COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_jetty_pgclient/bin/hexagon_jetty_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile index 18963d4dfe1..1d64e9246dd 100644 --- a/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:19-jre-alpine +FROM docker.io/eclipse-temurin:20-jre-alpine +ARG PROJECT=hexagon_jetty_postgresql + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_jetty_postgresql ENV JDK_JAVA_OPTIONS --enable-preview -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA -DvirtualThreads=true COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_jetty_postgresql/bin/hexagon_jetty_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-netty-async-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-netty-async-pgclient.dockerfile new file mode 100644 index 00000000000..09845f263cb --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon-netty-async-pgclient.dockerfile @@ -0,0 +1,23 @@ +# +# BUILD +# +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build +USER root +WORKDIR /hexagon + +ADD . . +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist + +# +# RUNTIME +# +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_netty_async_pgclient + +ENV POSTGRESQL_DB_HOST tfb-database +ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA + +COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT + +ENTRYPOINT [ "/opt/hexagon_netty_async_pgclient/bin/hexagon_netty_async_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-netty-native.dockerfile b/frameworks/Kotlin/hexagon/hexagon-netty-native.dockerfile new file mode 100644 index 00000000000..5443b48eb8f --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon-netty-native.dockerfile @@ -0,0 +1,21 @@ +# +# BUILD +# +FROM ghcr.io/graalvm/native-image:ol9-java17-22.3.2 as build +USER root +WORKDIR /hexagon + +ADD . . +RUN microdnf -y install findutils +RUN ./gradlew --quiet classes +RUN ./gradlew --quiet -x test nativeCompile + +# +# RUNTIME +# +FROM scratch +ARG PROJECT=hexagon_netty_postgresql + +COPY --from=build /hexagon/$PROJECT/build/native/nativeCompile/$PROJECT / + +ENTRYPOINT [ "/hexagon_netty_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-netty.dockerfile b/frameworks/Kotlin/hexagon/hexagon-netty.dockerfile index e343078fb6e..18fce97d813 100644 --- a/frameworks/Kotlin/hexagon/hexagon-netty.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-netty.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_netty_postgresql + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_netty_postgresql ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_netty_postgresql/bin/hexagon_netty_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile index d40959b0e0e..afe2e155ccc 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_nettyepoll_pgclient + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_nettyepoll_pgclient ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_nettyepoll_pgclient/bin/hexagon_nettyepoll_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile b/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile index 575378b8583..c8a5592b67e 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_nettyepoll_postgresql + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_nettyepoll_postgresql ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_nettyepoll_postgresql/bin/hexagon_nettyepoll_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile b/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile index 7ca5725be48..e35db7b9f68 100644 --- a/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile @@ -1,21 +1,21 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test war # # RUNTIME # -FROM tomcat:10.1.2-jre17-temurin +FROM docker.io/tomcat:10-jre17-temurin-jammy +ARG MODULE=/hexagon/hexagon_tomcat_postgresql + ENV POSTGRESQL_DB_HOST tfb-database -ENV MODULE /hexagon/hexagon_tomcat_postgresql ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build $MODULE/build/libs/ROOT.war /usr/local/tomcat/webapps/ROOT.war -EXPOSE 8080 diff --git a/frameworks/Kotlin/hexagon/hexagon-vertx-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-vertx-pgclient.dockerfile new file mode 100644 index 00000000000..5b8ff2cd1b1 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon-vertx-pgclient.dockerfile @@ -0,0 +1,23 @@ +# +# BUILD +# +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build +USER root +WORKDIR /hexagon + +ADD . . +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist + +# +# RUNTIME +# +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_vertx_pgclient + +ENV POSTGRESQL_DB_HOST tfb-database +ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA + +COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT + +ENTRYPOINT [ "/opt/hexagon_vertx_pgclient/bin/hexagon_vertx_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon.dockerfile b/frameworks/Kotlin/hexagon/hexagon.dockerfile index e228bd5a7db..6bc878580ab 100644 --- a/frameworks/Kotlin/hexagon/hexagon.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon.dockerfile @@ -1,24 +1,23 @@ # # BUILD # -FROM gradle:8.0.2-jdk17-alpine AS build +FROM docker.io/gradle:8.1.1-jdk17-alpine AS build USER root WORKDIR /hexagon ADD . . -RUN gradle --quiet compileRocker -RUN gradle --quiet -x test +RUN gradle --quiet classes +RUN gradle --quiet -x test installDist # # RUNTIME # -FROM eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:17-jre-alpine +ARG PROJECT=hexagon_jetty_postgresql + ENV POSTGRESQL_DB_HOST tfb-database -ENV PROJECT hexagon_jetty_postgresql ENV JDK_JAVA_OPTIONS -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -EXPOSE 9090 - -ENTRYPOINT /opt/$PROJECT/bin/$PROJECT +ENTRYPOINT [ "/opt/hexagon_jetty_postgresql/bin/hexagon_jetty_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/build.gradle b/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/build.gradle index 71e2dc0f44f..3b3d4b51b92 100644 --- a/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/build.gradle @@ -1,13 +1,7 @@ apply(from: "$gradleScripts/application.gradle") -application { - mainClass.set("com.hexagonkt.BenchmarkKt") -} - dependencies { api(project(":store_pgclient")) api("com.hexagonkt:http_server_jetty:$hexagonVersion") } - -build.dependsOn("installDist") diff --git a/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/build.gradle b/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/build.gradle index 09dde4a8327..059804ac9ff 100644 --- a/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/build.gradle @@ -1,13 +1,8 @@ apply(from: "$gradleScripts/application.gradle") - -application { - mainClass.set("com.hexagonkt.BenchmarkKt") -} +apply(from: "$gradleScripts/native.gradle") dependencies { api(project(":store_sql")) api("com.hexagonkt:http_server_jetty:$hexagonVersion") } - -build.dependsOn("installDist") diff --git a/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/build.gradle b/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/build.gradle new file mode 100644 index 00000000000..f29d1703b61 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/build.gradle @@ -0,0 +1,7 @@ + +apply(from: "$gradleScripts/application.gradle") + +dependencies { + api(project(":store_pgclient_async")) + api("com.hexagonkt:http_server_netty_async:$hexagonVersion") +} diff --git a/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/src/main/kotlin/Benchmark.kt new file mode 100644 index 00000000000..e5a9de4c597 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_netty_async_pgclient/src/main/kotlin/Benchmark.kt @@ -0,0 +1,25 @@ +package com.hexagonkt + +import com.hexagonkt.async.Benchmark +import com.hexagonkt.async.store.BenchmarkPgClientStore +import com.hexagonkt.http.server.netty.async.NettyServerAdapter +import com.hexagonkt.templates.rocker.RockerAdapter +import io.netty.util.ResourceLeakDetector +import io.netty.util.ResourceLeakDetector.Level.DISABLED +import java.net.URL + +fun main() { + ResourceLeakDetector.setLevel(DISABLED) + + System.setProperty("io.netty.buffer.checkBounds", "false") + System.setProperty("io.netty.buffer.checkAccessible", "false") + + val settings = Settings() + val store = BenchmarkPgClientStore("postgresql") + val templateEngine = RockerAdapter() + val templateUrl = URL("classpath:fortunes.rocker.html") + val engine = NettyServerAdapter(bossGroupThreads = 48) + + val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) + benchmark.server.start() +} diff --git a/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/build.gradle b/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/build.gradle index e06ac14aff0..01884cb3583 100644 --- a/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/build.gradle @@ -1,13 +1,8 @@ apply(from: "$gradleScripts/application.gradle") - -application { - mainClass.set("com.hexagonkt.BenchmarkKt") -} +apply(from: "$gradleScripts/native.gradle") dependencies { api(project(":store_sql")) api("com.hexagonkt:http_server_netty:$hexagonVersion") } - -build.dependsOn("installDist") diff --git a/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/src/main/kotlin/Benchmark.kt index 100af29d51e..2a95e7385fc 100644 --- a/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_netty_postgresql/src/main/kotlin/Benchmark.kt @@ -3,9 +3,16 @@ package com.hexagonkt import com.hexagonkt.http.server.netty.NettyServerAdapter import com.hexagonkt.store.BenchmarkSqlStore import com.hexagonkt.templates.rocker.RockerAdapter +import io.netty.util.ResourceLeakDetector +import io.netty.util.ResourceLeakDetector.Level.DISABLED import java.net.URL fun main() { + ResourceLeakDetector.setLevel(DISABLED) + + System.setProperty("io.netty.buffer.checkBounds", "false") + System.setProperty("io.netty.buffer.checkAccessible", "false") + val settings = Settings() val store = BenchmarkSqlStore("postgresql") val templateEngine = RockerAdapter() diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/build.gradle b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/build.gradle index 07ecf663690..0017123ec54 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/build.gradle @@ -1,14 +1,8 @@ apply(from: "$gradleScripts/application.gradle") -application { - mainClass.set("com.hexagonkt.BenchmarkKt") -} - dependencies { api(project(":store_pgclient")) api("com.hexagonkt:http_server_netty_epoll:$hexagonVersion") api("io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64") } - -build.dependsOn("installDist") diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt index abe085171f2..cf1cf7d998e 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt @@ -3,9 +3,16 @@ package com.hexagonkt import com.hexagonkt.http.server.netty.epoll.NettyEpollServerAdapter import com.hexagonkt.store.BenchmarkPgClientStore import com.hexagonkt.templates.rocker.RockerAdapter +import io.netty.util.ResourceLeakDetector +import io.netty.util.ResourceLeakDetector.Level.DISABLED import java.net.URL fun main() { + ResourceLeakDetector.setLevel(DISABLED) + + System.setProperty("io.netty.buffer.checkBounds", "false") + System.setProperty("io.netty.buffer.checkAccessible", "false") + val settings = Settings() val store = BenchmarkPgClientStore("postgresql") val templateEngine = RockerAdapter() diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/build.gradle b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/build.gradle index b314102ff80..243fa57c121 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/build.gradle @@ -1,14 +1,8 @@ apply(from: "$gradleScripts/application.gradle") -application { - mainClass.set("com.hexagonkt.BenchmarkKt") -} - dependencies { api(project(":store_sql")) api("com.hexagonkt:http_server_netty_epoll:$hexagonVersion") api("io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64") } - -build.dependsOn("installDist") diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt index d0c2aa58347..dcf1495705a 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt @@ -3,9 +3,16 @@ package com.hexagonkt import com.hexagonkt.http.server.netty.epoll.NettyEpollServerAdapter import com.hexagonkt.store.BenchmarkSqlStore import com.hexagonkt.templates.rocker.RockerAdapter +import io.netty.util.ResourceLeakDetector +import io.netty.util.ResourceLeakDetector.Level.DISABLED import java.net.URL fun main() { + ResourceLeakDetector.setLevel(DISABLED) + + System.setProperty("io.netty.buffer.checkBounds", "false") + System.setProperty("io.netty.buffer.checkAccessible", "false") + val settings = Settings() val store = BenchmarkSqlStore("postgresql") val templateEngine = RockerAdapter() diff --git a/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt b/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt index cdf911e1ee9..38a2731deee 100644 --- a/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt +++ b/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt @@ -2,8 +2,8 @@ package com.hexagonkt import com.hexagonkt.http.model.Header import com.hexagonkt.http.model.Headers -import com.hexagonkt.http.server.handlers.HttpHandler -import com.hexagonkt.http.server.handlers.OnHandler +import com.hexagonkt.http.handlers.HttpHandler +import com.hexagonkt.http.handlers.OnHandler import com.hexagonkt.http.server.servlet.ServletServer import com.hexagonkt.store.BenchmarkSqlStore import com.hexagonkt.templates.rocker.RockerAdapter diff --git a/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/build.gradle b/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/build.gradle new file mode 100644 index 00000000000..2d5cdaf23d7 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/build.gradle @@ -0,0 +1,9 @@ + +apply(from: "$gradleScripts/application.gradle") + +dependencies { + api(project(":store_pgclient_async")) + api("com.hexagonkt:http_server_vertx_async:$hexagonVersion") + api("io.vertx:vertx-io_uring-incubator:4.4.2") + api("io.netty:netty-transport-native-epoll:4.1.93.Final") +} diff --git a/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/src/main/kotlin/Benchmark.kt new file mode 100644 index 00000000000..6b52be6d68f --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_vertx_pgclient/src/main/kotlin/Benchmark.kt @@ -0,0 +1,33 @@ +package com.hexagonkt + +import com.hexagonkt.async.Benchmark +import com.hexagonkt.async.store.BenchmarkPgClientStore +import com.hexagonkt.http.server.vertx.VertxServerAdapter +import com.hexagonkt.templates.rocker.RockerAdapter +import io.netty.util.ResourceLeakDetector +import io.netty.util.ResourceLeakDetector.Level.DISABLED +import java.net.URL + +fun main() { + ResourceLeakDetector.setLevel(DISABLED) + + System.setProperty("vertx.disableMetrics", "true") + System.setProperty("vertx.disableH2c", "true") + System.setProperty("vertx.disableWebsockets", "true") + System.setProperty("vertx.flashPolicyHandler", "false") + System.setProperty("vertx.threadChecks", "false") + System.setProperty("vertx.disableContextTimings", "true") + System.setProperty("vertx.disableTCCL", "true") + System.setProperty("vertx.disableHttpHeadersValidation", "true") + System.setProperty("io.netty.buffer.checkBounds", "false") + System.setProperty("io.netty.buffer.checkAccessible", "false") + + val settings = Settings() + val store = BenchmarkPgClientStore("postgresql") + val templateEngine = RockerAdapter() + val templateUrl = URL("classpath:fortunes.rocker.html") + val engine = VertxServerAdapter(preferNativeTransport = true) + + val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) + benchmark.server.start() +} diff --git a/frameworks/Kotlin/hexagon/model/build.gradle b/frameworks/Kotlin/hexagon/model/build.gradle new file mode 100644 index 00000000000..bb97bfd9a3d --- /dev/null +++ b/frameworks/Kotlin/hexagon/model/build.gradle @@ -0,0 +1,4 @@ + +dependencies { + api("com.hexagonkt:core:$hexagonVersion") +} diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/Settings.kt b/frameworks/Kotlin/hexagon/model/src/main/kotlin/Settings.kt similarity index 100% rename from frameworks/Kotlin/hexagon/core/src/main/kotlin/Settings.kt rename to frameworks/Kotlin/hexagon/model/src/main/kotlin/Settings.kt diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/model/CachedWorld.kt b/frameworks/Kotlin/hexagon/model/src/main/kotlin/model/CachedWorld.kt similarity index 100% rename from frameworks/Kotlin/hexagon/core/src/main/kotlin/model/CachedWorld.kt rename to frameworks/Kotlin/hexagon/model/src/main/kotlin/model/CachedWorld.kt diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/model/Fortune.kt b/frameworks/Kotlin/hexagon/model/src/main/kotlin/model/Fortune.kt similarity index 100% rename from frameworks/Kotlin/hexagon/core/src/main/kotlin/model/Fortune.kt rename to frameworks/Kotlin/hexagon/model/src/main/kotlin/model/Fortune.kt diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/model/Message.kt b/frameworks/Kotlin/hexagon/model/src/main/kotlin/model/Message.kt similarity index 100% rename from frameworks/Kotlin/hexagon/core/src/main/kotlin/model/Message.kt rename to frameworks/Kotlin/hexagon/model/src/main/kotlin/model/Message.kt diff --git a/frameworks/Kotlin/hexagon/core/src/main/kotlin/model/World.kt b/frameworks/Kotlin/hexagon/model/src/main/kotlin/model/World.kt similarity index 100% rename from frameworks/Kotlin/hexagon/core/src/main/kotlin/model/World.kt rename to frameworks/Kotlin/hexagon/model/src/main/kotlin/model/World.kt diff --git a/frameworks/Kotlin/hexagon/settings.gradle b/frameworks/Kotlin/hexagon/settings.gradle index 2d571cdc706..7b6af470769 100644 --- a/frameworks/Kotlin/hexagon/settings.gradle +++ b/frameworks/Kotlin/hexagon/settings.gradle @@ -1,13 +1,18 @@ include( + "model", "core", + "core_async", "store_pgclient", + "store_pgclient_async", "store_sql", "hexagon_jetty_pgclient", "hexagon_jetty_postgresql", "hexagon_netty_postgresql", + "hexagon_netty_async_pgclient", "hexagon_nettyepoll_pgclient", "hexagon_nettyepoll_postgresql", + "hexagon_vertx_pgclient", "hexagon_tomcat_postgresql", ) diff --git a/frameworks/Kotlin/hexagon/store_pgclient/src/main/kotlin/BenchmarkPgClientStore.kt b/frameworks/Kotlin/hexagon/store_pgclient/src/main/kotlin/BenchmarkPgClientStore.kt index 5cd13ccee0a..1fb9547353f 100644 --- a/frameworks/Kotlin/hexagon/store_pgclient/src/main/kotlin/BenchmarkPgClientStore.kt +++ b/frameworks/Kotlin/hexagon/store_pgclient/src/main/kotlin/BenchmarkPgClientStore.kt @@ -24,7 +24,7 @@ class BenchmarkPgClientStore( private val connectOptions: PgConnectOptions by lazy { PgConnectOptions().apply { - host = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "localhost" + host = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "tfb-database" database = settings.databaseName user = settings.databaseUsername password = settings.databasePassword diff --git a/frameworks/Kotlin/hexagon/store_pgclient_async/build.gradle b/frameworks/Kotlin/hexagon/store_pgclient_async/build.gradle new file mode 100644 index 00000000000..65d4ca18f97 --- /dev/null +++ b/frameworks/Kotlin/hexagon/store_pgclient_async/build.gradle @@ -0,0 +1,6 @@ + +dependencies { + api(project(":core_async")) + implementation("io.vertx:vertx-pg-client:$vertxVersion") + implementation("com.ongres.scram:client:2.1") +} diff --git a/frameworks/Kotlin/hexagon/store_pgclient_async/src/main/kotlin/BenchmarkPgClientStore.kt b/frameworks/Kotlin/hexagon/store_pgclient_async/src/main/kotlin/BenchmarkPgClientStore.kt new file mode 100644 index 00000000000..8266b3120e4 --- /dev/null +++ b/frameworks/Kotlin/hexagon/store_pgclient_async/src/main/kotlin/BenchmarkPgClientStore.kt @@ -0,0 +1,114 @@ +package com.hexagonkt.async.store + +import com.hexagonkt.Settings +import com.hexagonkt.core.Jvm +import com.hexagonkt.model.CachedWorld +import com.hexagonkt.model.Fortune +import com.hexagonkt.model.World +import io.vertx.core.CompositeFuture.all +import io.vertx.core.Future +import io.vertx.core.Vertx.vertx +import io.vertx.pgclient.PgConnectOptions +import io.vertx.pgclient.PgPool +import io.vertx.sqlclient.* +import org.cache2k.Cache +import java.util.concurrent.CompletableFuture + +class BenchmarkPgClientStore( + engine: String, + private val settings: Settings = Settings(), +) : BenchmarkStore(settings) { + + companion object { + private const val SELECT_WORLD: String = "select * from world where id = $1" + private const val UPDATE_WORLD: String = "update world set randomNumber = $1 where id = $2" + private const val SELECT_ALL_FORTUNES: String = "select * from fortune" + } + + private val connectOptions: PgConnectOptions by lazy { + PgConnectOptions().apply { + host = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "tfb-database" + database = settings.databaseName + user = settings.databaseUsername + password = settings.databasePassword + cachePreparedStatements = true + } + } + + private val poolOptions: PoolOptions by lazy { + PoolOptions().apply { + val environment = Jvm.systemSettingOrNull("BENCHMARK_ENV")?.lowercase() + maxSize = 8 + if (environment == "citrine") Jvm.cpuCount else Jvm.cpuCount * 2 + } + } + + private val dataSource: SqlClient by lazy { PgPool.pool(vertx(), connectOptions, poolOptions) } + + override fun findAllFortunes(): CompletableFuture> = + dataSource.preparedQuery(SELECT_ALL_FORTUNES) + .execute() + .map { rowSet -> + rowSet.map { row -> Fortune(row.getInteger(0), row.getString(1)) } + } + .toCompletionStage() + .toCompletableFuture() + + override fun findWorlds(ids: List): CompletableFuture> { + val futures = ids.map { findWorld(it, dataSource) } + return all(futures).map { it.list() }.toCompletionStage().toCompletableFuture() + } + + override fun replaceWorlds(worlds: List): CompletableFuture<*> { + val futures = worlds.map { + val worldId = it.id + val newRandomNumber = it.randomNumber + dataSource + .preparedQuery(SELECT_WORLD) + .execute(Tuple.of(worldId)) + .flatMap { rowSet -> + val row = rowSet.iterator().next() + row.getInteger(1) // Read 'randomNumber' to comply with Test type 5, point 6 + dataSource + .preparedQuery(UPDATE_WORLD) + .execute(Tuple.of(newRandomNumber, worldId)) + } + } + return all(futures).toCompletionStage().toCompletableFuture() + } + + override fun initWorldsCache(cache: Cache) { + dataSource + .preparedQuery("select * from world") + .execute() + .map { rowSet -> + rowSet.map { row -> + val id = row.getInteger(0) + val randomNumber = row.getInteger(1) + cache.put(id, CachedWorld(id, randomNumber)) + } + } + .toCompletionStage() + .toCompletableFuture() + .get() + } + + override fun loadCachedWorld(id: Int): CachedWorld = + findWorld(id, dataSource) + .map { world -> CachedWorld(world.id, world.randomNumber) } + .toCompletionStage() + .toCompletableFuture() + .get() + + override fun close() { + dataSource.close() + } + + private fun findWorld(id: Int, client: SqlClient): Future = + client + .preparedQuery(SELECT_WORLD) + .execute(Tuple.of(id)) + .map { rowSet -> + val row = rowSet.iterator().next() + World(row.getInteger(0), row.getInteger(1)) + } +} diff --git a/frameworks/Kotlin/hexagon/store_sql/src/main/kotlin/BenchmarkSqlStore.kt b/frameworks/Kotlin/hexagon/store_sql/src/main/kotlin/BenchmarkSqlStore.kt index ea871ec1b13..501a4d9ce34 100644 --- a/frameworks/Kotlin/hexagon/store_sql/src/main/kotlin/BenchmarkSqlStore.kt +++ b/frameworks/Kotlin/hexagon/store_sql/src/main/kotlin/BenchmarkSqlStore.kt @@ -22,7 +22,7 @@ class BenchmarkSqlStore( } private val dataSource: HikariDataSource by lazy { - val dbHost = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "localhost" + val dbHost = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "tfb-database" val environment = Jvm.systemSettingOrNull(String::class, "BENCHMARK_ENV")?.lowercase() val poolSize = 8 + if (environment == "citrine") Jvm.cpuCount else Jvm.cpuCount * 2 val postgresqlSettings = listOf(