Browse Source

Hexagon (#4290)

* Update Hexagon benchmark

* Update Hexagon benchmark

* Remove features not used in tests

* Remove MySql storage

* Enable Resin test

* Upgrade Hexagon to v0.11

* Disable Resin

* Fix dependencies

* Improve template rendering

* Test in travis

* Fix build script

* Restore Travis script

* Restore Travis script

* MySQL store support and MongoDB fix

* Fix MySQL test

* Fix MySQL test

* Fix MySQL test

* Travis testing

* Fix MySQL test

* Restore Travis

* Take MySQL URL from other test

* Add PostgreSQL support

* Update version and tests

* Update version and tests

* Only test Hexagon in fork

* Fix config

* Fix config

* Update version and tests

* Remove Resin tests

* Restore Travis

* Restore Travis

* Upgrade framework version

* Reduce local tests temporarily

* Disable Resin tests

* Fix Gradle Wrapper issues

* Restore Resin tests

* Add Bintray repository

* Disable Resin backend

* Restore master's

* Upgrade framework version

* Test only Hexagon changes (temporary)

* Test Hexagon in Travis CI

* Add Undertow support

* Test only Undertow

* Restore Travis jobs

* Enable all Hexagon's variants

* Optimize benchmark

* Fix documentation

* Fix documentation

* Add Gradle Wrapper

* Move code to conform with Kotlin's coding standards

* Trace more information (only in tests)

* Add mini performance tests (to be sure everything would be fine in TFB)

* Support different template engines

* Add configuration properties

* Drop Undertow engine

* Update versions and dependencies

* Update documentation

* Ignore Gradle directories

* Update configuration

* Update benchmark

* Improve benchmark

* Improve benchmark dockerfiles

* Next Hexagon release

* Delete Gatlin simulation

* Fix url for testing

* Remove Gatling test

* Update Hexagon benchmark
Juanjo Aguililla 6 years ago
parent
commit
086984284f

+ 4 - 0
.gitignore

@@ -95,3 +95,7 @@ dependency-reduced-pom.xml
 .dart_tool/
 .dart_tool/
 *.packages
 *.packages
 pubspec.lock
 pubspec.lock
+
+# Gradle
+.gradle/
+build/

+ 0 - 6
frameworks/Kotlin/hexagon/README.md

@@ -39,9 +39,3 @@ and `${TEMPLATE_ENGINE}` with: `pebble`
 * Fortunes: http://localhost:8080/${DB_ENGINE}/${TEMPLATE_ENGINE}/fortunes
 * Fortunes: http://localhost:8080/${DB_ENGINE}/${TEMPLATE_ENGINE}/fortunes
 * Database updates: http://localhost:8080/${DB_ENGINE}/update
 * Database updates: http://localhost:8080/${DB_ENGINE}/update
 * Database queries: http://localhost:8080/${DB_ENGINE}/query
 * Database queries: http://localhost:8080/${DB_ENGINE}/query
-
-## Run inside vagrant
-
-Follow instructions at: https://github.com/TechEmpower/FrameworkBenchmarks#quick-start-guide-vagrant
-
-And run: `rm -rf ~/FrameworkBenchmarks/results` to clear tests results.

+ 24 - 2
frameworks/Kotlin/hexagon/benchmark_config.json

@@ -24,6 +24,28 @@
                 "notes": "http://hexagonkt.com",
                 "notes": "http://hexagonkt.com",
                 "versus": "servlet"
                 "versus": "servlet"
             },
             },
+            "resin-mongodb": {
+                "json_url": "/json",
+                "db_url": "/mongodb/db",
+                "query_url": "/mongodb/query?queries=",
+                "fortune_url": "/mongodb/pebble/fortunes",
+                "update_url": "/mongodb/update?queries=",
+                "plaintext_url": "/plaintext",
+                "port": 8080,
+                "approach": "Realistic",
+                "classification": "Micro",
+                "database": "mongodb",
+                "framework": "Hexagon",
+                "language": "Kotlin",
+                "orm": "Raw",
+                "platform": "Servlet",
+                "webserver": "None",
+                "os": "Linux",
+                "database_os": "Linux",
+                "display_name": "Hexagon Resin MongoDB",
+                "notes": "http://hexagonkt.com",
+                "versus": "servlet"
+            },
             "jetty-postgresql": {
             "jetty-postgresql": {
                 "json_url": "/json",
                 "json_url": "/json",
                 "db_url": "/postgresql/db",
                 "db_url": "/postgresql/db",
@@ -61,10 +83,10 @@
                 "language": "Kotlin",
                 "language": "Kotlin",
                 "orm": "Raw",
                 "orm": "Raw",
                 "platform": "Servlet",
                 "platform": "Servlet",
-                "webserver": "Resin",
+                "webserver": "None",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
-                "display_name": "Hexagon Jetty PostgreSQL",
+                "display_name": "Hexagon Resin PostgreSQL",
                 "notes": "http://hexagonkt.com",
                 "notes": "http://hexagonkt.com",
                 "versus": "servlet"
                 "versus": "servlet"
             }
             }

+ 16 - 19
frameworks/Kotlin/hexagon/build.gradle

@@ -1,42 +1,39 @@
 
 
 plugins {
 plugins {
-    id 'org.jetbrains.kotlin.jvm' version '1.3.10'
+    id "org.jetbrains.kotlin.jvm" version "1.3.11"
 }
 }
 
 
-apply from: "$gradleScripts/kotlin.gradle"
-apply from: "$gradleScripts/service.gradle"
+apply(from: "$gradleScripts/kotlin.gradle")
+apply(from: "$gradleScripts/service.gradle")
 
 
-apply plugin: 'war'
+apply(plugin: "war")
 
 
-defaultTasks 'installDist'
+defaultTasks("installDist")
 
 
 mainClassName = "com.hexagonkt.BenchmarkKt"
 mainClassName = "com.hexagonkt.BenchmarkKt"
-applicationDefaultJvmArgs = [
-    '-Xms2G', '-Xmx2G', '-XX:+UseNUMA', '-XX:+UseParallelGC', '-XX:+AggressiveOpts'
-]
+applicationDefaultJvmArgs = [ "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts" ]
 
 
 war {
 war {
     archiveName = "ROOT.war"
     archiveName = "ROOT.war"
 }
 }
 
 
-installDist.dependsOn 'war'
+installDist.dependsOn("war")
 
 
 dependencies {
 dependencies {
-    compile ("com.hexagonkt:store_mongodb:$hexagonVersion")
-    compile ("com.hexagonkt:server_jetty:$hexagonVersion")
-    compile ("com.hexagonkt:templates_pebble:$hexagonVersion")
+    compile("com.hexagonkt:store_mongodb:$hexagonVersion")
+    compile("com.hexagonkt:http_server_jetty:$hexagonVersion")
+    compile("com.hexagonkt:templates_pebble:$hexagonVersion")
 
 
-    compile ("ch.qos.logback:logback-classic:$logbackVersion")
-    compile ("com.zaxxer:HikariCP:$hikariVersion")
-    compile ("org.postgresql:postgresql:$postgresqlVersion")
+    compile("com.zaxxer:HikariCP:$hikariVersion")
+    compile("org.postgresql:postgresql:$postgresqlVersion")
 
 
     // providedCompile excludes the dependency only in the WAR, not in the distribution
     // providedCompile excludes the dependency only in the WAR, not in the distribution
-    providedCompile ("org.eclipse.jetty:jetty-webapp:$jettyVersion") { exclude module: "slf4j-api" }
+    providedCompile("org.eclipse.jetty:jetty-webapp:$jettyVersion") { exclude module: "slf4j-api" }
 
 
-    testCompile ("com.hexagonkt:port_client:$hexagonVersion")
-    testCompile ("org.testng:testng:$testngVersion")
+    testCompile("com.hexagonkt:port_http_client:$hexagonVersion")
+    testCompile("org.testng:testng:$testngVersion")
 }
 }
 
 
 test {
 test {
-    useTestNG ()
+    useTestNG()
 }
 }

+ 5 - 5
frameworks/Kotlin/hexagon/gradle.properties

@@ -1,10 +1,10 @@
 description=Hexagon web framework's benchmark
 description=Hexagon web framework's benchmark
-gradleScripts=https\://raw.githubusercontent.com/hexagonkt/hexagon/0.24.6/gradle
-hexagonVersion=0.24.6
+gradleScripts=https\://raw.githubusercontent.com/hexagonkt/hexagon/0.24.7/gradle
+hexagonVersion=0.24.7
 hikariVersion=3.2.0
 hikariVersion=3.2.0
-jettyVersion=9.4.12.v20180830
-kotlinVersion=1.3.10
-kotlinCoroutinesVersion=1.0.1
+jettyVersion=9.4.14.v20181114
+kotlinCoroutinesVersion=1.1.0
+kotlinVersion=1.3.11
 logbackVersion=1.2.3
 logbackVersion=1.2.3
 postgresqlVersion=42.2.5.jre7
 postgresqlVersion=42.2.5.jre7
 testngVersion=6.14.3
 testngVersion=6.14.3

+ 24 - 0
frameworks/Kotlin/hexagon/hexagon-resin-mongodb.dockerfile

@@ -0,0 +1,24 @@
+
+#
+# BUILD
+#
+FROM gradle:5.0.0-jdk11 AS gradle_build
+USER root
+WORKDIR /hexagon
+
+COPY src src
+COPY build.gradle build.gradle
+COPY gradle.properties gradle.properties
+RUN gradle --quiet --exclude-task test
+
+#
+# RUNTIME
+#
+FROM openjdk:11
+ENV DBSTORE mongodb
+ENV MONGODB_DB_HOST tfb-database
+ENV RESIN 4.0.58
+
+RUN curl http://caucho.com/download/resin-$RESIN.tar.gz | tar xvz -C /opt
+COPY --from=gradle_build /hexagon/build/libs/ROOT.war /opt/resin-$RESIN/webapps
+ENTRYPOINT /opt/resin-$RESIN/bin/resin.sh console

+ 55 - 71
frameworks/Kotlin/hexagon/src/main/kotlin/Benchmark.kt

@@ -1,22 +1,19 @@
 package com.hexagonkt
 package com.hexagonkt
 
 
-import com.hexagonkt.helpers.error
-import com.hexagonkt.helpers.Environment.systemSetting
-import com.hexagonkt.serialization.JsonFormat
+import com.hexagonkt.helpers.Jvm.systemSetting
+import com.hexagonkt.serialization.Json
 import com.hexagonkt.serialization.convertToMap
 import com.hexagonkt.serialization.convertToMap
-import com.hexagonkt.serialization.serialize
-import com.hexagonkt.server.*
-import com.hexagonkt.server.jetty.JettyServletAdapter
-import com.hexagonkt.server.servlet.ServletServer
-import com.hexagonkt.settings.SettingsManager.settings
+import com.hexagonkt.http.server.*
+import com.hexagonkt.http.server.jetty.JettyServletAdapter
+import com.hexagonkt.http.server.servlet.ServletServer
+import com.hexagonkt.settings.SettingsManager
 import com.hexagonkt.templates.TemplateManager.render
 import com.hexagonkt.templates.TemplateManager.render
 import com.hexagonkt.templates.TemplatePort
 import com.hexagonkt.templates.TemplatePort
 import com.hexagonkt.templates.pebble.PebbleAdapter
 import com.hexagonkt.templates.pebble.PebbleAdapter
 
 
-import java.util.*
-import java.util.concurrent.ThreadLocalRandom
+import java.util.Locale
+
 import javax.servlet.annotation.WebListener
 import javax.servlet.annotation.WebListener
-import java.net.InetAddress.getByName as address
 
 
 // DATA CLASSES
 // DATA CLASSES
 internal data class Message(val message: String)
 internal data class Message(val message: String)
@@ -27,43 +24,56 @@ internal data class World(val _id: Int, val id: Int, val randomNumber: Int)
 private const val TEXT_MESSAGE: String = "Hello, World!"
 private const val TEXT_MESSAGE: String = "Hello, World!"
 private const val QUERIES_PARAM: String = "queries"
 private const val QUERIES_PARAM: String = "queries"
 
 
-private val contentTypeJson: String = JsonFormat.contentType
-
-private val storageEngines: List<String> = listOf("mongodb", "postgresql")
-private val templateEngines: List<String> = listOf("pebble")
-
-internal val benchmarkStores: Map<String, Store> by lazy {
-    storageEngines.map { it to createStore(it) }.toMap()
+internal val benchmarkStores: Map<String, BenchmarkStore> by lazy {
+    mapOf(
+        "mongodb" to BenchmarkMongoDbStore("mongodb"),
+        "postgresql" to BenchmarkSqlStore("postgresql")
+    )
 }
 }
 
 
 internal val benchmarkTemplateEngines: Map<String, TemplatePort> by lazy {
 internal val benchmarkTemplateEngines: Map<String, TemplatePort> by lazy {
-    templateEngines.map {
-        when (it) {
-            "pebble" -> it to PebbleAdapter
-            else -> error("Unsupported template engine: $it")
-        }
-    }
-    .toMap()
+    mapOf("pebble" to PebbleAdapter)
 }
 }
 
 
-internal val benchmarkServer: Server by lazy {
-    val engine = when (systemSetting("WEBENGINE", "jetty")) {
+private val defaultLocale = Locale.getDefault()
+
+private val engine by lazy {
+    when (systemSetting("WEBENGINE", "jetty")) {
         "jetty" -> JettyServletAdapter()
         "jetty" -> JettyServletAdapter()
         else -> error("Unsupported server engine")
         else -> error("Unsupported server engine")
     }
     }
-
-    Server(engine, settings, router())
 }
 }
 
 
-// UTILITIES
-internal fun randomWorld(): Int = ThreadLocalRandom.current().nextInt(WORLD_ROWS) + 1
+private val router: Router by lazy {
+    Router {
+        before {
+            response.addHeader("Server", "Servlet/3.1")
+            response.addHeader("Transfer-Encoding", "chunked")
+        }
+
+        get("/plaintext") { ok(TEXT_MESSAGE, "text/plain") }
+        get("/json") { ok(Message(TEXT_MESSAGE), Json) }
+
+        benchmarkStores.forEach { storeEngine, store ->
+            benchmarkTemplateEngines.forEach { templateKind ->
+                val path = "/$storeEngine/${templateKind.key}/fortunes"
 
 
-private fun Call.returnWorlds(worldsList: List<World>) {
-    val worlds = worldsList.map { it.convertToMap() - "_id" }
+                get(path) { listFortunes(store, templateKind.key, templateKind.value) }
+            }
 
 
-    ok(worlds.serialize(), contentTypeJson)
+            get("/$storeEngine/db") { dbQuery(store) }
+            get("/$storeEngine/query") { getWorlds(store) }
+            get("/$storeEngine/update") { updateWorlds(store) }
+        }
+    }
 }
 }
 
 
+internal val benchmarkServer: Server by lazy { Server(engine, router, SettingsManager.settings) }
+
+// UTILITIES
+private fun returnWorlds(worldsList: List<World>): List<Map<Any?, Any?>> =
+    worldsList.map { it.convertToMap() - "_id" }
+
 private fun Call.getWorldsCount() = request[QUERIES_PARAM]?.toIntOrNull().let {
 private fun Call.getWorldsCount() = request[QUERIES_PARAM]?.toIntOrNull().let {
     when {
     when {
         it == null -> 1
         it == null -> 1
@@ -74,57 +84,31 @@ private fun Call.getWorldsCount() = request[QUERIES_PARAM]?.toIntOrNull().let {
 }
 }
 
 
 // HANDLERS
 // HANDLERS
-private fun Call.listFortunes(store: Store, templateKind: String, templateEngine: TemplatePort) {
+private fun Call.listFortunes(
+    store: BenchmarkStore, templateKind: String, templateAdapter: TemplatePort) {
+
     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 defaultLocale = Locale.getDefault()
 
 
     response.contentType = "text/html;charset=utf-8"
     response.contentType = "text/html;charset=utf-8"
-    ok(render(templateEngine, "fortunes.$templateKind.html", defaultLocale, context))
+    ok(render(templateAdapter, "fortunes.$templateKind.html", defaultLocale, context))
 }
 }
 
 
-private fun Call.dbQuery(store: Store) {
-    val world = store.findWorlds(1).first().convertToMap() - "_id"
-
-    ok(world.serialize(), contentTypeJson)
+private fun Call.dbQuery(store: BenchmarkStore) {
+    ok(returnWorlds(store.findWorlds(1)).first(), Json)
 }
 }
 
 
-private fun Call.getWorlds(store: Store) {
-    returnWorlds(store.findWorlds(getWorldsCount()))
+private fun Call.getWorlds(store: BenchmarkStore) {
+    ok(returnWorlds(store.findWorlds(getWorldsCount())), Json)
 }
 }
 
 
-private fun Call.updateWorlds(store: Store) {
-    returnWorlds(store.replaceWorlds(getWorldsCount()))
-}
-
-// CONTROLLER
-private fun router(): Router = router {
-
-    before {
-        response.addHeader("Server", "Servlet/3.1")
-        response.addHeader("Transfer-Encoding", "chunked")
-    }
-
-    get("/plaintext") { ok(TEXT_MESSAGE, "text/plain") }
-    get("/json") { ok(Message(TEXT_MESSAGE).serialize(), contentTypeJson) }
-
-    benchmarkStores.forEach { (storeEngine, store) ->
-        templateEngines.forEach { templateKind ->
-            val path = "/$storeEngine/$templateKind/fortunes"
-            val templateEngine = benchmarkTemplateEngines[templateKind] ?: error
-
-            get(path) { listFortunes(store, templateKind, templateEngine) }
-        }
-
-        get("/$storeEngine/db") { dbQuery(store) }
-        get("/$storeEngine/query") { getWorlds(store) }
-        get("/$storeEngine/update") { updateWorlds(store) }
-    }
+private fun Call.updateWorlds(store: BenchmarkStore) {
+    ok(returnWorlds(store.replaceWorlds(getWorldsCount())), Json)
 }
 }
 
 
 // SERVERS
 // SERVERS
-@WebListener class Web : ServletServer (router())
+@WebListener class Web : ServletServer(router)
 
 
 fun main() {
 fun main() {
     benchmarkServer.run()
     benchmarkServer.run()

+ 38 - 63
frameworks/Kotlin/hexagon/src/main/kotlin/BenchmarkStorage.kt

@@ -1,9 +1,9 @@
 package com.hexagonkt
 package com.hexagonkt
 
 
-import com.hexagonkt.helpers.Environment
-import com.hexagonkt.settings.SettingsManager.setting
-import com.mongodb.MongoClient
-import com.mongodb.MongoClientURI
+import com.hexagonkt.helpers.error
+import com.hexagonkt.helpers.Jvm.systemSetting
+import com.hexagonkt.settings.SettingsManager.defaultSetting
+import com.hexagonkt.store.mongodb.MongoDbStore
 
 
 import com.zaxxer.hikari.HikariConfig
 import com.zaxxer.hikari.HikariConfig
 import com.zaxxer.hikari.HikariDataSource
 import com.zaxxer.hikari.HikariDataSource
@@ -11,102 +11,73 @@ import com.zaxxer.hikari.HikariDataSource
 import java.sql.Connection
 import java.sql.Connection
 import java.sql.ResultSet.CONCUR_READ_ONLY
 import java.sql.ResultSet.CONCUR_READ_ONLY
 import java.sql.ResultSet.TYPE_FORWARD_ONLY
 import java.sql.ResultSet.TYPE_FORWARD_ONLY
-import kotlin.reflect.KClass
+import java.util.concurrent.ThreadLocalRandom
 
 
-import kotlin.reflect.KProperty1
-
-internal const val WORLD_ROWS = 10000
+internal const val WORLD_ROWS: Int = 10000
 
 
 private val worldName: String = defaultSetting("worldCollection", "world")
 private val worldName: String = defaultSetting("worldCollection", "world")
 private val fortuneName: String = defaultSetting("fortuneCollection", "fortune")
 private val fortuneName: String = defaultSetting("fortuneCollection", "fortune")
-private val databaseName = defaultSetting("database", "hello_world")
-
-internal fun <T : Any> defaultSetting(name: String, value: T): T = setting(name) ?: value
-
-private fun getDbUrl(engine: String): String {
-    val dbHost = Environment.systemSetting("${engine.toUpperCase()}_DB_HOST", "localhost")
-
-    return when (engine) {
-        "mongodb" -> "mongodb://$dbHost/$databaseName"
-        "postgresql" -> "jdbc:postgresql://$dbHost/$databaseName?" +
-            "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"
-        else -> error("Unsupported database")
-    }
-}
+private val databaseName: String = defaultSetting("database", "hello_world")
 
 
-internal fun createStore(engine: String): Store = when (engine) {
-    "mongodb" -> MongoDbStore(getDbUrl(engine))
-    "postgresql" -> SqlStore(getDbUrl(engine))
-    else -> error("Unsupported database")
-}
+internal fun randomWorld(): Int = ThreadLocalRandom.current().nextInt(WORLD_ROWS) + 1
 
 
-internal interface Store {
+internal interface BenchmarkStore {
     fun findAllFortunes(): List<Fortune>
     fun findAllFortunes(): List<Fortune>
     fun findWorlds(count: Int): List<World>
     fun findWorlds(count: Int): List<World>
     fun replaceWorlds(count: Int): List<World>
     fun replaceWorlds(count: Int): List<World>
     fun close()
     fun close()
 }
 }
 
 
-private class MongoDbStore(dbUrl: String) : Store {
-    private val database by lazy { MongoClient(MongoClientURI(dbUrl)).getDatabase(databaseName) }
+internal class BenchmarkMongoDbStore(engine: String) : BenchmarkStore {
 
 
-    private val worldRepository by lazy { repository(worldName, World::class, World::_id) }
-    private val fortuneRepository by lazy { repository(fortuneName, Fortune::class, Fortune::_id) }
+    private val dbHost: String = systemSetting("${engine.toUpperCase()}_DB_HOST", "localhost")
 
 
-    private fun <T : Any> repository(name: String, type: KClass<T>, key: KProperty1<T, Int>) =
-        com.hexagonkt.store.mongodb.MongoDbStore(type, key, name, database)
+    private val dbUrl: String = "mongodb://$dbHost/$databaseName"
 
 
-    override fun close() { /* Not needed */ }
+    private val worldRepository by lazy {
+        MongoDbStore(World::class, World::_id, dbUrl, worldName)
+    }
+
+    private val fortuneRepository by lazy {
+        MongoDbStore(Fortune::class, Fortune::_id, dbUrl, fortuneName)
+    }
 
 
-    override fun findAllFortunes() = fortuneRepository.findAll()
+    override fun findAllFortunes(): List<Fortune> = fortuneRepository.findAll()
 
 
-    override fun findWorlds(count: Int) =
+    override fun findWorlds(count: Int): List<World> =
         (1..count).mapNotNull { worldRepository.findOne(randomWorld()) }
         (1..count).mapNotNull { worldRepository.findOne(randomWorld()) }
 
 
-    override fun replaceWorlds(count: Int) = (1..count)
-        .map { worldRepository.findOne(randomWorld())?.copy(randomNumber = randomWorld()) }
-        .toList()
-        .filterNotNull()
+    override fun replaceWorlds(count: Int): List<World> = (1..count)
         .map {
         .map {
-            worldRepository.replaceOne(it)
-            it
+            val world = worldRepository.findOne(randomWorld()) ?: error
+            val worldCopy = world.copy(randomNumber = randomWorld())
+            worldRepository.replaceOne(worldCopy)
+            worldCopy
         }
         }
+
+    override fun close() { /* Not needed */ }
 }
 }
 
 
-private class SqlStore(jdbcUrl: String) : Store {
+internal class BenchmarkSqlStore(engine: String) : BenchmarkStore {
     companion object {
     companion object {
         private const val SELECT_WORLD = "select * from world where id = ?"
         private const val SELECT_WORLD = "select * from world where id = ?"
         private const val UPDATE_WORLD = "update world set randomNumber = ? where id = ?"
         private const val UPDATE_WORLD = "update world set randomNumber = ? where id = ?"
         private const val SELECT_ALL_FORTUNES = "select * from fortune"
         private const val SELECT_ALL_FORTUNES = "select * from fortune"
     }
     }
 
 
+    private val dbHost: String = systemSetting("${engine.toUpperCase()}_DB_HOST", "localhost")
+
+    private val jdbcUrl: String = "jdbc:postgresql://$dbHost/$databaseName"
+
     private val dataSource: HikariDataSource by lazy {
     private val dataSource: HikariDataSource by lazy {
         val config = HikariConfig()
         val config = HikariConfig()
         config.jdbcUrl = jdbcUrl
         config.jdbcUrl = jdbcUrl
-        config.maximumPoolSize = defaultSetting("maximumPoolSize", 16)
+        config.maximumPoolSize = defaultSetting("maximumPoolSize", 64)
         config.username = defaultSetting("databaseUsername", "benchmarkdbuser")
         config.username = defaultSetting("databaseUsername", "benchmarkdbuser")
         config.password = defaultSetting("databasePassword", "benchmarkdbpass")
         config.password = defaultSetting("databasePassword", "benchmarkdbpass")
         HikariDataSource(config)
         HikariDataSource(config)
     }
     }
 
 
-    override fun close() {
-        dataSource.close()
-    }
-
     override fun findAllFortunes(): List<Fortune> {
     override fun findAllFortunes(): List<Fortune> {
         var fortunes = listOf<Fortune>()
         var fortunes = listOf<Fortune>()
 
 
@@ -166,4 +137,8 @@ private class SqlStore(jdbcUrl: String) : Store {
 
 
         return worlds
         return worlds
     }
     }
+
+    override fun close() {
+        dataSource.close()
+    }
 }
 }

+ 1 - 1
frameworks/Kotlin/hexagon/src/main/resources/service.yaml

@@ -11,4 +11,4 @@ fortuneCollection : fortune
 databaseUsername : benchmarkdbuser
 databaseUsername : benchmarkdbuser
 databasePassword : benchmarkdbpass
 databasePassword : benchmarkdbpass
 
 
-maximumPoolSize : 32
+maximumPoolSize : 64

+ 11 - 17
frameworks/Kotlin/hexagon/src/test/kotlin/BenchmarkTest.kt

@@ -1,21 +1,21 @@
 package com.hexagonkt
 package com.hexagonkt
 
 
 import com.hexagonkt.serialization.parse
 import com.hexagonkt.serialization.parse
-import com.hexagonkt.client.Client
-import com.hexagonkt.serialization.JsonFormat
+import com.hexagonkt.http.client.Client
+import com.hexagonkt.serialization.Json
 import com.hexagonkt.serialization.parseList
 import com.hexagonkt.serialization.parseList
-import com.hexagonkt.HttpMethod.GET
+import com.hexagonkt.http.Method.GET
 import org.asynchttpclient.Response
 import org.asynchttpclient.Response
 import org.testng.annotations.AfterClass
 import org.testng.annotations.AfterClass
 import org.testng.annotations.BeforeClass
 import org.testng.annotations.BeforeClass
 import org.testng.annotations.Test
 import org.testng.annotations.Test
 import java.lang.System.setProperty
 import java.lang.System.setProperty
-import kotlin.test.assertFailsWith
 
 
-class BenchmarkJettyMongoDbTest : BenchmarkTest("jetty", "mongodb")
-class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
+@Test class BenchmarkJettyMongoDbTest : BenchmarkTestBase("jetty", "mongodb")
 
 
-@Test abstract class BenchmarkTest(
+@Test class BenchmarkJettyPostgreSqlTest : BenchmarkTestBase("jetty", "postgresql")
+
+@Test abstract class BenchmarkTestBase(
     private val webEngine: String,
     private val webEngine: String,
     private val databaseEngine: String,
     private val databaseEngine: String,
     private val templateEngine: String = "pebble"
     private val templateEngine: String = "pebble"
@@ -32,12 +32,6 @@ class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
         benchmarkServer.stop()
         benchmarkServer.stop()
     }
     }
 
 
-    @Test fun store() {
-        assertFailsWith<IllegalStateException> {
-            createStore("invalid")
-        }
-    }
-
     @Test fun web() {
     @Test fun web() {
         val web = Web()
         val web = Web()
 
 
@@ -60,7 +54,7 @@ class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
         val response = client.get("/json")
         val response = client.get("/json")
         val content = response.responseBody
         val content = response.responseBody
 
 
-        checkResponse(response, JsonFormat.contentType)
+        checkResponse(response, Json.contentType)
         assert("Hello, World!" == content.parse(Message::class).message)
         assert("Hello, World!" == content.parse(Message::class).message)
     }
     }
 
 
@@ -86,7 +80,7 @@ class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
         val response = client.get("/$databaseEngine/db")
         val response = client.get("/$databaseEngine/db")
         val body = response.responseBody
         val body = response.responseBody
 
 
-        checkResponse(response, JsonFormat.contentType)
+        checkResponse(response, Json.contentType)
         val bodyMap = body.parse(Map::class)
         val bodyMap = body.parse(Map::class)
         assert(bodyMap.containsKey(World::id.name))
         assert(bodyMap.containsKey(World::id.name))
         assert(bodyMap.containsKey(World::randomNumber.name))
         assert(bodyMap.containsKey(World::randomNumber.name))
@@ -96,7 +90,7 @@ class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
         val response = client.get("/$databaseEngine/update")
         val response = client.get("/$databaseEngine/update")
         val body = response.responseBody
         val body = response.responseBody
 
 
-        checkResponse(response, JsonFormat.contentType)
+        checkResponse(response, Json.contentType)
         val bodyMap = body.parseList(Map::class).first()
         val bodyMap = body.parseList(Map::class).first()
         assert(bodyMap.containsKey(World::id.name))
         assert(bodyMap.containsKey(World::id.name))
         assert(bodyMap.containsKey(World::randomNumber.name))
         assert(bodyMap.containsKey(World::randomNumber.name))
@@ -124,7 +118,7 @@ class BenchmarkJettyPostgreSqlTest : BenchmarkTest("jetty", "postgresql")
         val response = client.get(path)
         val response = client.get(path)
         val content = response.responseBody
         val content = response.responseBody
 
 
-        checkResponse(response, JsonFormat.contentType)
+        checkResponse(response, Json.contentType)
 
 
         val resultsList = content.parse(List::class)
         val resultsList = content.parse(List::class)
         assert(itemsCount == resultsList.size)
         assert(itemsCount == resultsList.size)

+ 0 - 1
frameworks/Kotlin/hexagon/src/test/resources/logback-test.xml

@@ -17,5 +17,4 @@
   </root>
   </root>
 
 
   <logger name="com.hexagonkt" level="trace" />
   <logger name="com.hexagonkt" level="trace" />
-  <logger name="BENCHMARK_LOGGER" level="trace" />
 </configuration>
 </configuration>

+ 0 - 68
frameworks/Kotlin/hexagon/src/test/scala/com/hexagonkt/BenchmarkSimulation.scala

@@ -1,68 +0,0 @@
-package com.hexagonkt
-
-import java.lang.System.getProperty
-
-import io.gatling.core.Predef._
-import io.gatling.core.structure.ScenarioBuilder
-import io.gatling.http.Predef._
-import io.gatling.http.request.builder.HttpRequestBuilder
-
-// TODO Make this test fail when the assertions are not meet (now prints KO but test pass)
-class BenchmarkSimulation extends Simulation {
-  private val host: String = property("host", "127.0.0.1")
-  private val port: Int = property("port", "0").toInt
-  private val databaseEngine: String = property("databaseEngine", "mongodb")
-  private val templateEngine: String = property("templateEngine", "pebble")
-  private val users: Int = property("users", "256").toInt
-  private val protocol: String = property("protocol", "http")
-  private val count: Int = property("count", "32").toInt
-
-  private val jsonRequest = get("json", "/json")
-  private val plaintextRequest = get("plaintext", "/plaintext")
-  private val dbRequest = get("db", s"/$databaseEngine/db")
-  private val queryRequest = get("query", s"/$databaseEngine/query")
-  private val queryBatchRequest = get("queryBatch", s"/$databaseEngine/query?queries=$count")
-  private val updateRequest = get("update", s"/$databaseEngine/update")
-  private val updateBatchRequest = get("updateBatch", s"/$databaseEngine/update?queries=$count")
-  private val fortunesRequest = get("fortunes", s"/$databaseEngine/$templateEngine/fortunes")
-
-  val checkScenario: ScenarioBuilder = scenario("CheckScenario")
-    .exec(jsonRequest.check(regex(".*\"message\" : \"Hello, World!\".*")))
-    .exec(plaintextRequest.check(regex(".*Hello, World!.*")))
-    .exec(dbRequest.check(regex(".*\"id\".*")).check(regex(".*\"randomNumber\".*")))
-    .exec(queryRequest.check(regex(".*\"id\".*")).check(regex(".*\"randomNumber\".*")))
-    .exec(queryBatchRequest.check(regex(".*\"id\".*")).check(regex(".*\"randomNumber\".*")))
-    .exec(updateRequest.check(regex(".*\"id\".*")).check(regex(".*\"randomNumber\".*")))
-    .exec(updateBatchRequest.check(regex(".*\"id\".*")).check(regex(".*\"randomNumber\".*")))
-    .exec(fortunesRequest
-      .check(regex(".*&quot;This should not be displayed.*"))
-      .check(regex(".*フレームワークのベンチマーク.*"))
-    )
-
-  private val runtimePort =
-    if (port == 0) {
-      BenchmarkKt.main()
-      BenchmarkKt.getBenchmarkServer.getRuntimePort
-    }
-    else port
-
-  after {
-    if (BenchmarkKt.getBenchmarkServer != null)
-      BenchmarkKt.getBenchmarkServer.stop()
-  }
-
-  setUp(checkScenario.inject(rampUsers(users) during 2))
-    .protocols(http.baseUrl(s"$protocol://$host:$runtimePort").contentTypeHeader("text/plain"))
-    .assertions(global.successfulRequests.percent.gte(100))
-
-  private def property(name: String, default: String): String =
-    if (getProperty(name) != null) getProperty(name)
-    else default
-
-  private def get(name: String, url: String): HttpRequestBuilder =
-    http(name + "Request").get(url)
-      .check(header("Server"))
-      .check(header("Transfer-Encoding"))
-      .check(header("Date"))
-      .check(header("Content-Type"))
-}

+ 0 - 19
frameworks/Kotlin/hexagon/src/test/scala/com/hexagonkt/GatlingTest.scala

@@ -1,19 +0,0 @@
-package com.hexagonkt
-
-import io.gatling.app.Gatling
-import io.gatling.core.config.GatlingPropertiesBuilder
-import org.testng.annotations.Test
-
-@Test class GatlingTest {
-
-  @Test def runGatlingStressTests () {
-
-    val properties = new GatlingPropertiesBuilder
-    val buildDir = System.getProperty("buildDir")
-
-    properties.simulationClass (classOf [BenchmarkSimulation].getName)
-    properties.resultsDirectory(if (buildDir == null) "build" else buildDir)
-
-    Gatling.fromMap (properties.build)
-  }
-}