Browse Source

Hexagon: Add Netty Epoll benchmark (#7314)

* 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
Juanjo Aguililla 3 years ago
parent
commit
e6f4bf0d83

+ 22 - 4
frameworks/Kotlin/hexagon/README.md

@@ -6,11 +6,11 @@ of web development platforms. The test utilizes Hexagon routes, serialization an
 
 
 ## Tests
 ## Tests
 
 
-You can run tests against any running server passing the `verify.endpoint` project property. I.e.:
-`./gradlew verify -Pverify.endpoint=http://host:1234`
+You can verify the benchmarks with the following command (from the project root):
+`./tfb --mode verify --test hexagon hexagon-jetty hexagon-tomcat hexagon-netty hexagon-nettyepoll`
 
 
-* [Hexagon Web](src/main/kotlin/com/hexagonkt/Benchmark.kt)
-* [Hexagon Storage](src/main/kotlin/com/hexagonkt/BenchmarkStorage.kt)
+To run the full benchmarks locally, on the project root (not this directory) execute:
+`./tfb --mode benchmark --test hexagon hexagon-jetty hexagon-tomcat hexagon-netty hexagon-nettyepoll`
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 
 
@@ -31,6 +31,24 @@ and `${TEMPLATE_ENGINE}` with: `pebble`
 * Database updates: http://localhost:9090/${DB_ENGINE}/update
 * Database updates: http://localhost:9090/${DB_ENGINE}/update
 * Database queries: http://localhost:9090/${DB_ENGINE}/query
 * Database queries: http://localhost:9090/${DB_ENGINE}/query
 
 
+### Netty
+
+* JSON Encoding Test: http://localhost:9090/json
+* Plain Text Test: http://localhost:9090/plaintext
+* Data-Store/Database Mapping Test: http://localhost:9090/${DB_ENGINE}/db?queries=5
+* Fortunes: http://localhost:9090/${DB_ENGINE}/${TEMPLATE_ENGINE}/fortunes
+* Database updates: http://localhost:9090/${DB_ENGINE}/update
+* Database queries: http://localhost:9090/${DB_ENGINE}/query
+
+### Netty Epoll
+
+* JSON Encoding Test: http://localhost:9090/json
+* Plain Text Test: http://localhost:9090/plaintext
+* Data-Store/Database Mapping Test: http://localhost:9090/${DB_ENGINE}/db?queries=5
+* Fortunes: http://localhost:9090/${DB_ENGINE}/${TEMPLATE_ENGINE}/fortunes
+* Database updates: http://localhost:9090/${DB_ENGINE}/update
+* Database queries: http://localhost:9090/${DB_ENGINE}/query
+
 ### Tomcat
 ### Tomcat
 
 
 * JSON Encoding Test: http://localhost:8080/json
 * JSON Encoding Test: http://localhost:8080/json

+ 23 - 0
frameworks/Kotlin/hexagon/benchmark_config.json

@@ -48,6 +48,29 @@
                 "notes": "http://hexagonkt.com",
                 "notes": "http://hexagonkt.com",
                 "versus": "netty"
                 "versus": "netty"
             },
             },
+            "nettyepoll": {
+                "json_url": "/json",
+                "db_url": "/postgresql/db",
+                "query_url": "/postgresql/query?queries=",
+                "fortune_url": "/postgresql/pebble/fortunes",
+                "update_url": "/postgresql/update?queries=",
+                "cached_query_url": "/postgresql/cached?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 Epoll PostgreSQL",
+                "notes": "http://hexagonkt.com",
+                "versus": "netty"
+            },
             "tomcat": {
             "tomcat": {
                 "json_url": "/json",
                 "json_url": "/json",
                 "db_url": "/postgresql/db",
                 "db_url": "/postgresql/db",

+ 7 - 4
frameworks/Kotlin/hexagon/build.gradle

@@ -1,14 +1,15 @@
 
 
 plugins {
 plugins {
-    id "org.jetbrains.kotlin.jvm" version "1.6.10"
+    id "org.jetbrains.kotlin.jvm" version "1.6.21"
 }
 }
 
 
 ext {
 ext {
-    hexagonVersion = "2.0.5"
+    hexagonVersion = "2.0.8"
     hikariVersion = "5.0.1"
     hikariVersion = "5.0.1"
-    jettyVersion = "11.0.8"
-    postgresqlVersion = "42.3.3"
+    jettyVersion = "11.0.9"
+    postgresqlVersion = "42.3.4"
     cache2kVersion = "2.6.1.Final"
     cache2kVersion = "2.6.1.Final"
+    nettyVersion = "4.1.76.Final"
 
 
     gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/$hexagonVersion/gradle"
     gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/$hexagonVersion/gradle"
 }
 }
@@ -32,11 +33,13 @@ installDist.dependsOn("war")
 
 
 dependencies {
 dependencies {
     implementation("com.hexagonkt:http_server_netty:$hexagonVersion")
     implementation("com.hexagonkt:http_server_netty:$hexagonVersion")
+    implementation("com.hexagonkt:http_server_netty_epoll:$hexagonVersion")
     implementation("com.hexagonkt:http_server_jetty:$hexagonVersion")
     implementation("com.hexagonkt:http_server_jetty:$hexagonVersion")
     implementation("com.hexagonkt:templates_pebble:$hexagonVersion")
     implementation("com.hexagonkt:templates_pebble:$hexagonVersion")
     implementation("com.hexagonkt:logging_slf4j_jul:$hexagonVersion")
     implementation("com.hexagonkt:logging_slf4j_jul:$hexagonVersion")
     implementation("com.hexagonkt:serialization_jackson_json:$hexagonVersion")
     implementation("com.hexagonkt:serialization_jackson_json:$hexagonVersion")
 
 
+    implementation("io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64")
     implementation("org.cache2k:cache2k-core:$cache2kVersion")
     implementation("org.cache2k:cache2k-core:$cache2kVersion")
     implementation("com.zaxxer:HikariCP:$hikariVersion")
     implementation("com.zaxxer:HikariCP:$hikariVersion")
     implementation("org.postgresql:postgresql:$postgresqlVersion")
     implementation("org.postgresql:postgresql:$postgresqlVersion")

+ 18 - 0
frameworks/Kotlin/hexagon/config.toml

@@ -37,6 +37,24 @@ platform = "Netty"
 webserver = "None"
 webserver = "None"
 versus = "netty"
 versus = "netty"
 
 
+[nettyepoll]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+urls.db = "/postgresql/db"
+urls.query = "/postgresql/query?queries="
+urls.update = "/postgresql/update?queries="
+urls.fortune = "/postgresql/pebble/fortunes"
+urls.cached_query = "/postgresql/cached?count="
+approach = "Realistic"
+classification = "Micro"
+database = "postgres"
+database_os = "Linux"
+os = "Linux"
+orm = "Raw"
+platform = "Netty"
+webserver = "None"
+versus = "netty"
+
 [tomcat]
 [tomcat]
 urls.plaintext = "/plaintext"
 urls.plaintext = "/plaintext"
 urls.json = "/json"
 urls.json = "/json"

+ 2 - 2
frameworks/Kotlin/hexagon/hexagon-netty.dockerfile

@@ -1,7 +1,7 @@
 #
 #
 # BUILD
 # BUILD
 #
 #
-FROM gradle:7.4-jdk11 AS gradle_build
+FROM gradle:7.4.2-jdk11 AS gradle_build
 USER root
 USER root
 WORKDIR /hexagon
 WORKDIR /hexagon
 
 
@@ -12,7 +12,7 @@ RUN gradle --quiet
 #
 #
 # RUNTIME
 # RUNTIME
 #
 #
-FROM adoptopenjdk:11-jre-hotspot-bionic
+FROM eclipse-temurin:17-jre-alpine
 ENV DBSTORE postgresql
 ENV DBSTORE postgresql
 ENV POSTGRESQL_DB_HOST tfb-database
 ENV POSTGRESQL_DB_HOST tfb-database
 ENV WEBENGINE netty
 ENV WEBENGINE netty

+ 26 - 0
frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile

@@ -0,0 +1,26 @@
+#
+# BUILD
+#
+FROM gradle:7.4.2-jdk11 AS gradle_build
+USER root
+WORKDIR /hexagon
+
+COPY src src
+COPY build.gradle build.gradle
+RUN gradle --quiet
+
+#
+# RUNTIME
+#
+FROM eclipse-temurin:17-jre-alpine
+ENV DBSTORE postgresql
+ENV POSTGRESQL_DB_HOST tfb-database
+ENV WEBENGINE netty_epoll
+ENV PROJECT hexagon
+ENV DISABLE_CHECKS true
+
+COPY --from=gradle_build /hexagon/build/install/$PROJECT /opt/$PROJECT
+
+EXPOSE 9090
+
+ENTRYPOINT /opt/$PROJECT/bin/$PROJECT

+ 1 - 1
frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile

@@ -1,7 +1,7 @@
 #
 #
 # BUILD
 # BUILD
 #
 #
-FROM gradle:7.4-jdk11 AS gradle_build
+FROM gradle:7.4.2-jdk11 AS gradle_build
 USER root
 USER root
 WORKDIR /hexagon
 WORKDIR /hexagon
 
 

+ 2 - 2
frameworks/Kotlin/hexagon/hexagon.dockerfile

@@ -1,7 +1,7 @@
 #
 #
 # BUILD
 # BUILD
 #
 #
-FROM gradle:7.4-jdk11 AS gradle_build
+FROM gradle:7.4.2-jdk11 AS gradle_build
 USER root
 USER root
 WORKDIR /hexagon
 WORKDIR /hexagon
 
 
@@ -12,7 +12,7 @@ RUN gradle --quiet
 #
 #
 # RUNTIME
 # RUNTIME
 #
 #
-FROM adoptopenjdk:11-jre-hotspot-bionic
+FROM eclipse-temurin:17-jre-alpine
 ENV DBSTORE postgresql
 ENV DBSTORE postgresql
 ENV POSTGRESQL_DB_HOST tfb-database
 ENV POSTGRESQL_DB_HOST tfb-database
 ENV WEBENGINE jetty
 ENV WEBENGINE jetty

+ 2 - 0
frameworks/Kotlin/hexagon/src/main/kotlin/Benchmark.kt

@@ -5,6 +5,7 @@ import com.hexagonkt.http.server.HttpServerPort
 import com.hexagonkt.http.server.HttpServerSettings
 import com.hexagonkt.http.server.HttpServerSettings
 import com.hexagonkt.http.server.jetty.JettyServletAdapter
 import com.hexagonkt.http.server.jetty.JettyServletAdapter
 import com.hexagonkt.http.server.netty.NettyServerAdapter
 import com.hexagonkt.http.server.netty.NettyServerAdapter
+import com.hexagonkt.http.server.netty.epoll.NettyEpollServerAdapter
 import com.hexagonkt.store.BenchmarkSqlStore
 import com.hexagonkt.store.BenchmarkSqlStore
 import com.hexagonkt.store.BenchmarkStore
 import com.hexagonkt.store.BenchmarkStore
 import com.hexagonkt.templates.TemplatePort
 import com.hexagonkt.templates.TemplatePort
@@ -29,6 +30,7 @@ private val engines: Map<String, HttpServerPort> by lazy {
             sendXPoweredBy = settings.sendXPoweredBy,
             sendXPoweredBy = settings.sendXPoweredBy,
         ),
         ),
         "netty" to NettyServerAdapter(),
         "netty" to NettyServerAdapter(),
+        "netty_epoll" to NettyEpollServerAdapter(),
     )
     )
 }
 }
 
 

+ 4 - 3
frameworks/Kotlin/hexagon/src/main/kotlin/Controller.kt

@@ -55,7 +55,8 @@ class Controller(
             stores.forEach { (storeEngine, store) ->
             stores.forEach { (storeEngine, store) ->
                 path("/$storeEngine") {
                 path("/$storeEngine") {
                     templateEngines.forEach { (templateEngineId, templateEngine) ->
                     templateEngines.forEach { (templateEngineId, templateEngine) ->
-                        get("/${templateEngineId}/fortunes") { listFortunes(store, templateEngineId, templateEngine) }
+                        val templateUrl = templates.require(templateEngineId)
+                        get("/${templateEngineId}/fortunes") { listFortunes(store, templateUrl, templateEngine) }
                     }
                     }
 
 
                     get("/db") { dbQuery(store) }
                     get("/db") { dbQuery(store) }
@@ -68,13 +69,13 @@ class Controller(
     }
     }
 
 
     private fun HttpServerContext.listFortunes(
     private fun HttpServerContext.listFortunes(
-        store: BenchmarkStore, templateKind: String, templateAdapter: TemplatePort
+        store: BenchmarkStore, templateUrl: URL, templateAdapter: TemplatePort
     ): HttpServerContext {
     ): HttpServerContext {
 
 
         val fortunes = store.findAllFortunes() + Fortune(0, "Additional fortune added at request time.")
         val fortunes = store.findAllFortunes() + Fortune(0, "Additional fortune added at request time.")
         val sortedFortunes = fortunes.sortedBy { it.message }
         val sortedFortunes = fortunes.sortedBy { it.message }
         val context = mapOf("fortunes" to sortedFortunes)
         val context = mapOf("fortunes" to sortedFortunes)
-        val body = templateAdapter.render(templates.require(templateKind), context)
+        val body = templateAdapter.render(templateUrl, context)
 
 
         return ok(body, contentType = html)
         return ok(body, contentType = html)
     }
     }

+ 19 - 1
frameworks/Kotlin/hexagon/src/main/kotlin/store/BenchmarkSqlStore.kt

@@ -24,8 +24,26 @@ internal class BenchmarkSqlStore(engine: String, private val settings: Settings
         val dbHost = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "localhost"
         val dbHost = Jvm.systemSettingOrNull("${engine.uppercase()}_DB_HOST") ?: "localhost"
         val environment = Jvm.systemSettingOrNull(String::class, "BENCHMARK_ENV")?.lowercase()
         val environment = Jvm.systemSettingOrNull(String::class, "BENCHMARK_ENV")?.lowercase()
         val poolSize = 8 + if (environment == "citrine") Jvm.cpuCount else Jvm.cpuCount * 2
         val poolSize = 8 + if (environment == "citrine") Jvm.cpuCount else Jvm.cpuCount * 2
+        val postgresqlSettings = listOf(
+            "useSSL=false",
+            "jdbcCompliantTruncation=false",
+            "elideSetAutoCommits=true",
+            "useLocalSessionState=true",
+            "cachePrepStmts=true",
+            "cacheCallableStmts=true",
+            "alwaysSendSetIsolation=false",
+            "prepStmtCacheSize=4096",
+            "cacheServerConfiguration=true",
+            "prepStmtCacheSqlLimit=2048",
+            "traceProtocol=false",
+            "useUnbufferedInput=false",
+            "useReadAheadInput=false",
+            "maintainTimeStats=false",
+            "useServerPrepStmts=true",
+            "cacheRSMetadata=true"
+        ).joinToString("&")
         val config = HikariConfig().apply {
         val config = HikariConfig().apply {
-            jdbcUrl = "jdbc:postgresql://$dbHost/${settings.databaseName}"
+            jdbcUrl = "jdbc:postgresql://$dbHost/${settings.databaseName}?$postgresqlSettings"
             maximumPoolSize = Jvm.systemSettingOrNull(Int::class, "maximumPoolSize") ?: poolSize
             maximumPoolSize = Jvm.systemSettingOrNull(Int::class, "maximumPoolSize") ?: poolSize
             driverClassName = settings.databaseDriver
             driverClassName = settings.databaseDriver
             username = settings.databaseUsername
             username = settings.databaseUsername