diff --git a/.gitignore b/.gitignore
index 5508a94..b3f1835 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ target/
.project
/.idea/*
.vscode
+results.csv
diff --git a/README.md b/README.md
index a6cbaf3..19a2005 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ JMH benchmark for popular Java template engines:
Running the benchmark
======================
-1. Download the source code and build it (`mvn clean install`)
+1. Download the source code and build it (`mvn clean package`)
2. (Optional) To run a benchmark for a single template, such as Mustache, use `java -jar target/benchmarks.jar Mustache`
3. Run the benchmark for `presentations` or `stocks` workload. E.g. for : `presentations`
```bash
diff --git a/pom.xml b/pom.xml
index 5daf679..fd6a358 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,8 +25,13 @@
4.3.1
1.4.0
- 1.8.20
+ 21
+ 21
+ 21
+
+ 2.0.0
0.8.0
+ 0.4.0
@@ -233,6 +238,12 @@
${kotlinx.html.version}
+
+ nu.staldal
+ kotlin-html-builder
+ ${kotlin.html.builder.version}
+
+
junit
junit
diff --git a/src/main/java/com/mitchellbosecke/benchmark/KotlinHtmlBuilder.java b/src/main/java/com/mitchellbosecke/benchmark/KotlinHtmlBuilder.java
new file mode 100644
index 0000000..adbbec3
--- /dev/null
+++ b/src/main/java/com/mitchellbosecke/benchmark/KotlinHtmlBuilder.java
@@ -0,0 +1,29 @@
+package com.mitchellbosecke.benchmark;
+
+import com.mitchellbosecke.benchmark.model.Presentation;
+import com.mitchellbosecke.benchmark.model.Stock;
+import com.mitchellbosecke.benchmark.templates.PresentationsKotlin;
+import com.mitchellbosecke.benchmark.templates.PresentationsKotlinHtmlBuilder;
+import com.mitchellbosecke.benchmark.templates.StocksKotlin;
+import com.mitchellbosecke.benchmark.templates.StocksKotlinHtmlBuilder;
+import org.openjdk.jmh.annotations.Benchmark;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+public class KotlinHtmlBuilder extends BaseBenchmark {
+
+ private List stocks = Stock.dummyItems();
+ private final Collection presentations = Presentation.dummyItems();
+
+ @Benchmark
+ public String stocks(){
+ return StocksKotlinHtmlBuilder.Companion.stocksTemplate(stocks);
+ }
+
+ @Benchmark
+ public String presentations() throws IOException {
+ return PresentationsKotlinHtmlBuilder.Companion.presentationsTemplate(presentations);
+ }
+}
diff --git a/src/main/java/com/mitchellbosecke/benchmark/templates/PresentationsKotlinHtmlBuilder.kt b/src/main/java/com/mitchellbosecke/benchmark/templates/PresentationsKotlinHtmlBuilder.kt
new file mode 100644
index 0000000..5684b8c
--- /dev/null
+++ b/src/main/java/com/mitchellbosecke/benchmark/templates/PresentationsKotlinHtmlBuilder.kt
@@ -0,0 +1,52 @@
+package com.mitchellbosecke.benchmark.templates
+
+import com.mitchellbosecke.benchmark.model.Presentation
+import nu.staldal.kotlin.html.*
+
+class PresentationsKotlinHtmlBuilder {
+ companion object {
+
+ fun presentationsTemplate(presentations : Collection ): String {
+ return htmlDoc(prettyPrint = false) {
+ html {
+ head {
+ meta("charset" to "utf-8")
+ meta("name" to "viewport", "content" to "width=device-width, initial-scale=1.0")
+ meta("httpEquiv" to "contentLanguage", "content" to "IE=Edge")
+ title {
+ text("JFall 2013 Presentations - htmlApi")
+ }
+ link(
+ "rel" to "stylesheet",
+ "href" to "/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css",
+ "media" to "screen"
+ )
+ }
+ body {
+ div("class" to "container") {
+ div("class" to "page-header") {
+ h1 { text("JFall 2013 Presentations - htmlApi") }
+ }
+
+ presentations.forEach {
+ div("class" to "panel panel-default") {
+ div("class" to "panel-heading") {
+ h3("class" to "panel-title") {
+ text(it.title + " - " + it.speakerName)
+ }
+ }
+ div("class" to "panel-body") {
+ text(it.summary)
+ }
+ }
+ }
+ }
+
+ script("src" to "/webjars/jquery/3.1.1/jquery.min.js")
+ script("src" to "/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js")
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/mitchellbosecke/benchmark/templates/StocksKotlinHtmlBuilder.kt b/src/main/java/com/mitchellbosecke/benchmark/templates/StocksKotlinHtmlBuilder.kt
new file mode 100644
index 0000000..8cadffc
--- /dev/null
+++ b/src/main/java/com/mitchellbosecke/benchmark/templates/StocksKotlinHtmlBuilder.kt
@@ -0,0 +1,59 @@
+package com.mitchellbosecke.benchmark.templates
+
+import com.mitchellbosecke.benchmark.model.Stock
+import nu.staldal.kotlin.html.*
+
+class StocksKotlinHtmlBuilder {
+ companion object {
+
+ fun stocksTemplate(stocks : List ): String {
+ return htmlDoc(prettyPrint = false) {
+ html {
+ head {
+ title { text("Stock Prices") }
+ meta("httpEquiv" to "contentType", "content" to "text/html; charset=UTF-8")
+ meta("httpEquiv" to "Content-Style-Type", "content" to "text/css")
+ meta("httpEquiv" to "Content-Script-Type", "content" to "text/javascript")
+ link("rel" to "shortcut icon", "href" to "/images/favicon.ico")
+ link("rel" to "stylesheet", "type" to "text/css", "href" to "/css/style.css", "media" to "all")
+ script("type" to "text/javascript", "src" to "/js/util.js")
+ style("type" to "text/css") {
+ unsafe("[body { color: #333333; line-height: 150%;}thead { font-weight: bold; background-color: #CCCCCC;}.odd { background-color: #FFCCCC;}.even { background-color: #CCCCFF;}.minus { color: #FF0000;}]]>")
+ }
+ }
+ body {
+ h1 { text("Stock Prices") }
+ table {
+ thead {
+ tr {
+ th { text("#") }
+ th { text("symbol") }
+ th { text("name") }
+ th { text("price") }
+ th { text("change") }
+ th { text("ratio") }
+ }
+ }
+ tbody {
+ var index = 0
+ stocks.forEach {
+ tr("class" to if (index % 2 == 0) "even" else "odd") {
+ td { index++ }
+ td { a("href" to it.url) { text(it.name) } }
+ td { strong { text(it.price.toString()) } }
+ td(*if (it.change < 0) arrayOf("class" to "minus") else arrayOf()) {
+ text(it.change.toString())
+ }
+ td(*if (it.ratio < 0) arrayOf("class" to "minus") else arrayOf()) {
+ text(it.ratio.toString())
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}