Răsfoiți Sursa

quarkus with async postgres (#5459)

jringuette 5 ani în urmă
părinte
comite
6ad1a1419d
28 a modificat fișierele cu 674 adăugiri și 101 ștergeri
  1. 30 13
      frameworks/Java/quarkus/README.md
  2. 33 0
      frameworks/Java/quarkus/base/pom.xml
  3. 45 0
      frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java
  4. 48 0
      frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/model/Fortune.java
  5. 7 5
      frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/model/World.java
  6. 4 3
      frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/resource/JsonResource.java
  7. 3 2
      frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java
  8. 0 0
      frameworks/Java/quarkus/base/src/main/resources/fortunes.mustache
  9. 46 4
      frameworks/Java/quarkus/benchmark_config.json
  10. 26 0
      frameworks/Java/quarkus/hibernate/pom.xml
  11. 2 2
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java
  12. 53 0
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java
  13. 2 3
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java
  14. 8 3
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java
  15. 21 12
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java
  16. 4 4
      frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java
  17. 0 1
      frameworks/Java/quarkus/hibernate/src/main/resources/application.properties
  18. 25 0
      frameworks/Java/quarkus/pgclient/pom.xml
  19. 40 0
      frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java
  20. 46 0
      frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java
  21. 101 0
      frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java
  22. 58 0
      frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java
  23. 9 0
      frameworks/Java/quarkus/pgclient/src/main/resources/application.properties
  24. 16 29
      frameworks/Java/quarkus/pom.xml
  25. 18 0
      frameworks/Java/quarkus/quarkus-hibernate.dockerfile
  26. 18 0
      frameworks/Java/quarkus/quarkus-pgclient.dockerfile
  27. 11 5
      frameworks/Java/quarkus/quarkus.dockerfile
  28. 0 15
      frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

+ 30 - 13
frameworks/Java/quarkus/README.md

@@ -2,37 +2,50 @@
 
 This is the Quarkus portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
-There is currently one repository implementation.
-* [WorldRepository](src/main/java/io/quarkus/benchmark/repository/WorldRepository.java) is using JPA.
+## Implementations
+There is currently two repository implementations.
+
+### Hibernate via JPA
+* [WorldRepository](hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java)
+* [FortuneRepository](hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java)
+
+### Asynchronous DB accesses via pgclient
+* [WorldRepository](pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java)
+* [FortuneRepository](pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java)
+
 
 ### Plaintext Test
 
-* [Plaintext test source](src/main/java/io/quarkus/benchmark/resource/PlainTextResource.java)
+* [Plaintext test source](base/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java)
 
 ### JSON Serialization Test
 
-* [JSON test source](src/main/java/io/quarkus/benchmark/resource/JsonResource.java)
+* [JSON test source](base/src/main/java/io/quarkus/benchmark/resource/JsonResource.java)
 
 ### Database Query Test
 
-* [Database Query test source](src/main/java/io/quarkus/benchmark/resource/DbResource.java)
+* [Hibernate Database Query test source](hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java)
+* [PGClient Database Query test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java)
 
 ### Database Queries Test
 
-* [Database Queries test source](src/main/java/io/quarkus/benchmark/resource/DbResource.java)
+* [Hibernate Database Query test source](hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java)
+* [PGClient Database Query test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java)
 
 ### Database Update Test
 
-* [Database Update test source](src/main/java/io/quarkus/benchmark/resource/DbResource.java)
+* [Hibernate Database Query test source](hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java)
+* [PGClient Database Query test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java)
 
 ### Template rendering Test
 
-* [Template rendering test source](src/main/java/io/quarkus/benchmark/resource/FortuneResource.java)
+* [Hibernate Template rendering test source](hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java)
+* [PGClient Template rendering test source](pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java)
 
 ## Versions
 
 * [Java OpenJDK 11](http://openjdk.java.net/)
-* [Quarkus 0.16.0](https://quarkus.io)
+* [Quarkus 1.1.1](https://quarkus.io)
 
 ## Test URLs
 
@@ -46,16 +59,20 @@ There is currently one repository implementation.
 
 ### Database Query Test
 
-    http://localhost:8080/db
+    http://localhost:8080/hibernate/db
+    http://localhost:8080/pgclient/db
 
 ### Database Queries Test
 
-    http://localhost:8080/queries?queries=5
+    http://localhost:8080/hibernate/queries?queries=5
+    http://localhost:8080/pgclient/queries?queries=5
 
 ### Database Update Test
 
-    http://localhost:8080/updates?queries=5
+    http://localhost:8080/hibernate/updates?queries=5
+    http://localhost:8080/pgclient/updates?queries=5
 
 ### Template rendering Test
 
-    http://localhost:8080/fortunes
+    http://localhost:8080/hibernate/fortunes
+    http://localhost:8080/pgclient/fortunes

+ 33 - 0
frameworks/Java/quarkus/base/pom.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>base</artifactId>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.jandex</groupId>
+                <artifactId>jandex-maven-plugin</artifactId>
+                <version>1.0.7</version>
+                <executions>
+                    <execution>
+                        <id>make-index</id>
+                        <goals>
+                            <goal>jandex</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 45 - 0
frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -0,0 +1,45 @@
+package io.quarkus.benchmark.filter;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.util.HttpHeaderNames;
+
+@Provider
+public class ServerHeaderFilter implements ContainerResponseFilter {
+
+    private final DateHelper dateHelper = new DateHelper();
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
+        responseContext.getHeaders().add("Server", "Quarkus");
+        responseContext.getHeaders().add(HttpHeaderNames.DATE, dateHelper.getDate());
+    }
+
+    static class DateHelper extends TimerTask {
+        private Timer timer = new Timer();
+        private String date = generateDate();
+
+        public DateHelper() {
+            timer.schedule(this, 0, 1000);
+        }
+
+        @Override
+        public void run() {
+            date = generateDate();
+        }
+
+        private String generateDate() {
+            return java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(java.time.ZonedDateTime.now());
+        }
+
+        public String getDate() {
+            return date;
+        }
+    }
+}

+ 48 - 0
frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/model/Fortune.java

@@ -0,0 +1,48 @@
+package io.quarkus.benchmark.model;
+
+import java.util.Objects;
+
+public class Fortune {
+
+    private int id;
+    private String message;
+
+    public Fortune() {}
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Fortune fortune = (Fortune) o;
+        return id == fortune.id &&
+                Objects.equals(message, fortune.message);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, message);
+    }
+}

+ 7 - 5
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/model/World.java → frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/model/World.java

@@ -2,16 +2,18 @@ package io.quarkus.benchmark.model;
 
 import java.util.Objects;
 
-import javax.persistence.Entity;
-import javax.persistence.Id;
-
-@Entity
 public class World {
 
-    @Id
     private int id;
     private int randomNumber;
 
+    public World() {}
+
+    public World(int id, int randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
     public int getId() {
         return id;
     }

+ 4 - 3
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/resource/JsonResource.java → frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/resource/JsonResource.java

@@ -1,12 +1,13 @@
 package io.quarkus.benchmark.resource;
 
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
 
 @Path("/json")
 public class JsonResource {

+ 3 - 2
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java → frameworks/Java/quarkus/base/src/main/java/io/quarkus/benchmark/resource/PlaintextResource.java

@@ -1,11 +1,12 @@
 package io.quarkus.benchmark.resource;
 
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
 
 @Path("/plaintext")
 public class PlaintextResource {

+ 0 - 0
frameworks/Java/quarkus/src/main/resources/fortunes.mustache → frameworks/Java/quarkus/base/src/main/resources/fortunes.mustache


+ 46 - 4
frameworks/Java/quarkus/benchmark_config.json

@@ -5,9 +5,6 @@
       "default": {
         "json_url": "/json",
         "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "fortune_url": "/fortunes",
         "port": 8080,
         "approach": "Realistic",
         "classification": "fullstack",
@@ -20,7 +17,52 @@
         "webserver": "None",
         "os": "Linux",
         "database_os": "Linux",
-        "display_name": "Quarkus",
+        "display_name": "quarkus",
+        "notes": "",
+        "versus": "Netty"
+      }
+    },
+    {
+      "hibernate": {
+        "db_url": "/hibernate/db",
+        "query_url": "/hibernate/queries?queries=",
+        "fortune_url": "/hibernate/fortunes",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "full",
+        "platform": "JAX-RS",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "quarkus-hibernate",
+        "notes": "",
+        "versus": "Netty"
+      }
+    },
+    {
+      "pgclient": {
+        "db_url": "/pgclient/db",
+        "query_url": "/pgclient/queries?queries=",
+        "update_url": "/pgclient/updates?queries=",
+        "fortune_url": "/pgclient/fortunes",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "fullstack",
+        "database": "Postgres",
+        "framework": "Quarkus",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "JAX-RS",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "quarkus-pgclient",
         "notes": "",
         "versus": "Netty"
       }

+ 26 - 0
frameworks/Java/quarkus/hibernate/pom.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>hibernate</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus.benchmark</groupId>
+            <artifactId>base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-orm</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 2 - 2
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/model/Fortune.java → frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/Fortune.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.model;
+package io.quarkus.benchmark.model.hibernate;
 
 import java.util.Objects;
 
@@ -6,7 +6,7 @@ import javax.persistence.Entity;
 import javax.persistence.Id;
 
 @Entity
-public final class Fortune {
+public class Fortune {
 
     @Id
     private int id;

+ 53 - 0
frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/model/hibernate/World.java

@@ -0,0 +1,53 @@
+package io.quarkus.benchmark.model.hibernate;
+
+import java.util.Objects;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+
+    @Id
+    private int id;
+    private int randomNumber;
+
+    public World() {}
+
+    public World(int id, int randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        World world = (World) o;
+        return id == world.id &&
+                randomNumber == world.randomNumber;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, randomNumber);
+    }
+}

+ 2 - 3
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/repository/FortuneRepository.java → frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/FortuneRepository.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.repository;
+package io.quarkus.benchmark.repository.hibernate;
 
 import java.util.List;
 
@@ -8,8 +8,7 @@ import javax.persistence.EntityManager;
 import javax.persistence.Query;
 import javax.transaction.Transactional;
 
-import io.quarkus.benchmark.model.Fortune;
-import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.model.hibernate.Fortune;
 
 @ApplicationScoped
 public class FortuneRepository {

+ 8 - 3
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/repository/WorldRepository.java → frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/repository/hibernate/WorldRepository.java

@@ -1,11 +1,11 @@
-package io.quarkus.benchmark.repository;
+package io.quarkus.benchmark.repository.hibernate;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.transaction.Transactional;
 
-import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.model.hibernate.World;
 
 @ApplicationScoped
 public class WorldRepository {
@@ -18,10 +18,15 @@ public class WorldRepository {
         return em.find(World.class, id);
     }
 
+    @Transactional
+    public void update(World world) {
+        em.merge(world);
+    }
+
     @Transactional
     public void update(World[] worlds) {
         for (World world : worlds) {
-            em.merge(world);
+            update(world);
         }
     }
 }

+ 21 - 12
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/resource/DbResource.java → frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/DbResource.java

@@ -1,10 +1,11 @@
-package io.quarkus.benchmark.resource;
+package io.quarkus.benchmark.resource.hibernate;
 
 import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
+import javax.transaction.Transactional;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -12,15 +13,20 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
-import io.quarkus.benchmark.model.World;
-import io.quarkus.benchmark.repository.WorldRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.quarkus.benchmark.model.hibernate.World;
+import io.quarkus.benchmark.repository.hibernate.WorldRepository;
 
 @ApplicationScoped
-@Path("/")
+@Path("/hibernate")
 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public class DbResource {
 
+    private static Logger LOG = LoggerFactory.getLogger(DbResource.class);
+
     @Inject
     WorldRepository worldRepository;
 
@@ -41,18 +47,21 @@ public class DbResource {
     @GET
     @Path("/updates")
     public World[] updates(@QueryParam("queries") String queries) {
-        var worlds = new World[parseQueryCount(queries)];
-        Arrays.setAll(worlds, i -> {
-            World world = randomWorld();
-            world.setRandomNumber(randomWorldNumber());
-            return world;
-        });
-
-        worldRepository.update(worlds);
+        int count = parseQueryCount(queries);
+        var worlds = new World[count];
+        Arrays.setAll(worlds, i -> updateOne());
 
         return worlds;
     }
 
+    @Transactional
+    public World updateOne() {
+        World world = randomWorld();
+        world.setRandomNumber(randomWorldNumber());
+        worldRepository.update(world);
+        return world;
+    }
+
     private World randomWorld() {
         return worldRepository.find(randomWorldNumber());
     }

+ 4 - 4
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/resource/FortuneResource.java → frameworks/Java/quarkus/hibernate/src/main/java/io/quarkus/benchmark/resource/hibernate/FortuneResource.java

@@ -1,4 +1,4 @@
-package io.quarkus.benchmark.resource;
+package io.quarkus.benchmark.resource.hibernate;
 
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -20,11 +20,11 @@ import com.github.mustachejava.DefaultMustacheFactory;
 import com.github.mustachejava.Mustache;
 import com.github.mustachejava.MustacheFactory;
 
-import io.quarkus.benchmark.model.Fortune;
-import io.quarkus.benchmark.repository.FortuneRepository;
+import io.quarkus.benchmark.model.hibernate.Fortune;
+import io.quarkus.benchmark.repository.hibernate.FortuneRepository;
 
 @ApplicationScoped
-@Path("/")
+@Path("/hibernate")
 @Produces(MediaType.TEXT_HTML)
 @Consumes(MediaType.APPLICATION_JSON)
 public class FortuneResource {

+ 0 - 1
frameworks/Java/quarkus/src/main/resources/application.properties → frameworks/Java/quarkus/hibernate/src/main/resources/application.properties

@@ -9,7 +9,6 @@ quarkus.log.console.enable=true
 quarkus.log.console.level=DEBUG
 quarkus.log.file.enable=false
 quarkus.log.level=INFO
-
 quarkus.log.category."org.hibernate".level=INFO
 
 quarkus.hibernate-orm.log.sql=false

+ 25 - 0
frameworks/Java/quarkus/pgclient/pom.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.quarkus</groupId>
+        <artifactId>benchmark</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+
+    <groupId>io.quarkus.benchmark</groupId>
+    <artifactId>pgclient</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus.benchmark</groupId>
+            <artifactId>base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-reactive-pg-client</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 40 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/FortuneRepository.java

@@ -0,0 +1,40 @@
+package io.quarkus.benchmark.repository.pgclient;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.reactivex.Scheduler;
+import io.reactivex.Single;
+import io.reactivex.schedulers.Schedulers;
+import io.vertx.reactivex.pgclient.PgPool;
+import io.vertx.reactivex.sqlclient.Row;
+import io.vertx.reactivex.sqlclient.RowSet;
+
+@ApplicationScoped
+public class FortuneRepository {
+
+    @Inject
+    PgPool client;
+
+    private final Scheduler scheduler = Schedulers.from(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2));
+
+    public Single<List<Fortune>> findAll() {
+        return client.rxQuery("SELECT id, message FROM fortune")
+                .map(RowSet::iterator)
+                .map(rowIterator -> {
+                    List<Fortune> fortunes = new ArrayList<>();
+                    while (rowIterator.hasNext()) {
+                        Row row = rowIterator.next();
+                        Fortune fortune = new Fortune(row.getInteger(0), row.getString(1));
+                        fortunes.add(fortune);
+                    }
+                    return fortunes;
+                })
+                .subscribeOn(scheduler);
+    }
+}

+ 46 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/repository/pgclient/WorldRepository.java

@@ -0,0 +1,46 @@
+package io.quarkus.benchmark.repository.pgclient;
+
+import java.util.concurrent.Executors;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.quarkus.benchmark.model.World;
+import io.reactivex.Maybe;
+import io.reactivex.Scheduler;
+import io.reactivex.Single;
+import io.reactivex.schedulers.Schedulers;
+import io.vertx.reactivex.pgclient.PgPool;
+import io.vertx.reactivex.sqlclient.RowIterator;
+import io.vertx.reactivex.sqlclient.RowSet;
+import io.vertx.reactivex.sqlclient.Tuple;
+
+@ApplicationScoped
+public class WorldRepository {
+
+    private static Logger LOG = LoggerFactory.getLogger(WorldRepository.class);
+
+    @Inject
+    PgPool client;
+
+    private final Scheduler scheduler = Schedulers.from(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2));
+
+    public Maybe<World> find(int id) {
+        return client.rxPreparedQuery("SELECT id, randomnumber FROM world WHERE id = $1", Tuple.of(id))
+                .map(RowSet::iterator)
+                .filter(RowIterator::hasNext)
+                .map(RowIterator::next)
+                .map(row -> new World(row.getInteger(0), row.getInteger(1)))
+                .subscribeOn(scheduler);
+    }
+
+    public Single<World> update(World world) {
+        return client.rxPreparedQuery("UPDATE world SET randomnumber = $1 WHERE id = $2",
+                Tuple.of(world.getRandomNumber(), world.getId()))
+                .map(rows -> world)
+                .subscribeOn(scheduler);
+    }
+}

+ 101 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/DbResource.java

@@ -0,0 +1,101 @@
+package io.quarkus.benchmark.resource.pgclient;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.quarkus.benchmark.model.World;
+import io.quarkus.benchmark.repository.pgclient.WorldRepository;
+import io.reactivex.Maybe;
+import io.reactivex.Single;
+
+@ApplicationScoped
+@Path("/pgclient")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class DbResource {
+
+    private static Logger LOG = LoggerFactory.getLogger(WorldRepository.class);
+
+    @Inject
+    WorldRepository worldRepository;
+
+    @GET
+    @Path("/db")
+    public CompletionStage<World> db() {
+        return randomWorld()
+                .to(m -> {
+                    CompletableFuture<World> cf = new CompletableFuture<>();
+                    m.subscribe(cf::complete, cf::completeExceptionally, () -> cf.complete(null));
+                    return cf;
+                });
+    }
+
+    @GET
+    @Path("/queries")
+    public CompletionStage<List<World>> queries(@QueryParam("queries") String queries) {
+        Maybe<World>[] worlds = new Maybe[parseQueryCount(queries)];
+        Arrays.setAll(worlds, i -> randomWorld());
+
+        return Maybe.concatArray(worlds)
+                .toList()
+                .to(m -> {
+                    CompletableFuture<List<World>> cf = new CompletableFuture<>();
+                    m.subscribe(cf::complete, cf::completeExceptionally);
+                    return cf;
+                });
+    }
+
+    @GET
+    @Path("/updates")
+    public CompletionStage<List<World>> updates(@QueryParam("queries") String queries) {
+        Single<World>[] worlds = new Single[parseQueryCount(queries)];
+        Arrays.setAll(worlds, i -> randomWorld().flatMapSingle(world -> {
+            world.setId(randomWorldNumber());
+            return worldRepository.update(world);
+        }));
+
+        return Single.concatArray(worlds)
+                .toList()
+                .to(m -> {
+                    CompletableFuture<List<World>> cf = new CompletableFuture<>();
+                    m.subscribe(cf::complete, cf::completeExceptionally);
+                    return cf;
+                });
+    }
+
+    private Maybe<World> randomWorld() {
+        return worldRepository.find(randomWorldNumber());
+    }
+
+    private int randomWorldNumber() {
+        return 1 + ThreadLocalRandom.current().nextInt(10000);
+    }
+
+    private int parseQueryCount(String textValue) {
+        if (textValue == null) {
+            return 1;
+        }
+        int parsedValue;
+        try {
+            parsedValue = Integer.parseInt(textValue);
+        } catch (NumberFormatException e) {
+            return 1;
+        }
+        return Math.min(500, Math.max(1, parsedValue));
+    }
+}

+ 58 - 0
frameworks/Java/quarkus/pgclient/src/main/java/io/quarkus/benchmark/resource/pgclient/FortuneResource.java

@@ -0,0 +1,58 @@
+package io.quarkus.benchmark.resource.pgclient;
+
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import io.quarkus.benchmark.model.Fortune;
+import io.quarkus.benchmark.repository.pgclient.FortuneRepository;
+
+@ApplicationScoped
+@Path("/pgclient")
+@Produces(MediaType.TEXT_HTML)
+@Consumes(MediaType.APPLICATION_JSON)
+public class FortuneResource {
+
+    @Inject
+    FortuneRepository repository;
+
+    private final Mustache template;
+
+    public FortuneResource() {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        template = mf.compile("fortunes.mustache");
+    }
+
+    @GET
+    @Path("/fortunes")
+    public CompletionStage<String> fortunes() {
+        return repository.findAll()
+                .map(fortunes -> {
+                    fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+                    fortunes.sort(Comparator.comparing(fortune -> fortune.getMessage()));
+
+                    StringWriter writer = new StringWriter();
+                    template.execute(writer, Collections.singletonMap("fortunes", fortunes));
+
+                    return writer.toString();
+                }).to(m -> {
+                    CompletableFuture<String> cf = new CompletableFuture<>();
+                    m.subscribe(cf::complete, cf::completeExceptionally);
+                    return cf;
+                });
+    }
+}

+ 9 - 0
frameworks/Java/quarkus/pgclient/src/main/resources/application.properties

@@ -0,0 +1,9 @@
+quarkus.datasource.url=vertx-reactive:postgresql://tfb-database:5432/hello_world
+quarkus.datasource.username=benchmarkdbuser
+quarkus.datasource.password=benchmarkdbpass
+quarkus.datasource.max-size=64
+quarkus.log.console.enable=true
+quarkus.log.console.level=INFO
+quarkus.log.file.enable=false
+quarkus.log.level=INFO
+quarkus.thread-pool.queue-size=2147483647

+ 16 - 29
frameworks/Java/quarkus/pom.xml

@@ -5,14 +5,21 @@
     <groupId>io.quarkus</groupId>
     <artifactId>benchmark</artifactId>
     <version>1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
 
     <properties>
-        <quarkus.version>0.16.0</quarkus.version>
+        <quarkus.version>1.1.1.Final</quarkus.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>11</maven.compiler.source>
         <maven.compiler.target>11</maven.compiler.target>
     </properties>
 
+    <modules>
+        <module>base</module>
+        <module>hibernate</module>
+        <module>pgclient</module>
+    </modules>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
@@ -22,6 +29,11 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <dependency>
+                <groupId>io.quarkus.benchmark</groupId>
+                <artifactId>base</artifactId>
+                <version>${project.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -38,10 +50,6 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-arc</artifactId>
         </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-hibernate-orm</artifactId>
-        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-jdbc-postgresql</artifactId>
@@ -92,30 +100,9 @@
     <profiles>
         <profile>
             <id>native</id>
-            <activation>
-                <property>
-                    <name>native</name>
-                </property>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>io.quarkus</groupId>
-                        <artifactId>quarkus-maven-plugin</artifactId>
-                        <version>${quarkus.version}</version>
-                        <executions>
-                            <execution>
-                                <goals>
-                                    <goal>native-image</goal>
-                                </goals>
-                                <configuration>
-                                    <enableHttpUrlHandler>true</enableHttpUrlHandler>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
         </profile>
     </profiles>
 </project>

+ 18 - 0
frameworks/Java/quarkus/quarkus-hibernate.dockerfile

@@ -0,0 +1,18 @@
+FROM maven:3.6.1-jdk-11-slim as maven
+WORKDIR /quarkus
+COPY pom.xml pom.xml
+COPY base/pom.xml base/pom.xml
+COPY hibernate/pom.xml hibernate/pom.xml
+COPY pgclient/pom.xml pgclient/pom.xml
+RUN mvn dependency:go-offline -q -pl base
+COPY base/src base/src
+COPY hibernate/src hibernate/src
+COPY pgclient/src pgclient/src
+
+RUN mvn package -q -pl hibernate -am
+
+FROM openjdk:11.0.3-jdk-slim
+WORKDIR /quarkus
+COPY --from=maven /quarkus/hibernate/target/lib lib
+COPY --from=maven /quarkus/hibernate/target/hibernate-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]

+ 18 - 0
frameworks/Java/quarkus/quarkus-pgclient.dockerfile

@@ -0,0 +1,18 @@
+FROM maven:3.6.1-jdk-11-slim as maven
+WORKDIR /quarkus
+COPY pom.xml pom.xml
+COPY base/pom.xml base/pom.xml
+COPY hibernate/pom.xml hibernate/pom.xml
+COPY pgclient/pom.xml pgclient/pom.xml
+RUN mvn dependency:go-offline -q -pl base
+COPY base/src base/src
+COPY hibernate/src hibernate/src
+COPY pgclient/src pgclient/src
+
+RUN mvn package -q -pl pgclient -am
+
+FROM openjdk:11.0.3-jdk-slim
+WORKDIR /quarkus
+COPY --from=maven /quarkus/pgclient/target/lib lib
+COPY --from=maven /quarkus/pgclient/target/pgclient-1.0-SNAPSHOT-runner.jar app.jar
+CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dquarkus.profile=pgclient", "-jar", "app.jar"]

+ 11 - 5
frameworks/Java/quarkus/quarkus.dockerfile

@@ -1,12 +1,18 @@
 FROM maven:3.6.1-jdk-11-slim as maven
 WORKDIR /quarkus
 COPY pom.xml pom.xml
-RUN mvn dependency:go-offline -q
-COPY src src
-RUN mvn package -q
+COPY base/pom.xml base/pom.xml
+COPY hibernate/pom.xml hibernate/pom.xml
+COPY pgclient/pom.xml pgclient/pom.xml
+RUN mvn dependency:go-offline -q -pl base
+COPY base/src base/src
+COPY hibernate/src hibernate/src
+COPY pgclient/src pgclient/src
+
+RUN mvn package -q -pl base
 
 FROM openjdk:11.0.3-jdk-slim
 WORKDIR /quarkus
-COPY --from=maven /quarkus/target/lib lib
-COPY --from=maven /quarkus/target/benchmark-1.0-SNAPSHOT-runner.jar app.jar
+COPY --from=maven /quarkus/base/target/lib lib
+COPY --from=maven /quarkus/base/target/base-1.0-SNAPSHOT-runner.jar app.jar
 CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"]

+ 0 - 15
frameworks/Java/quarkus/src/main/java/io/quarkus/benchmark/filter/ServerHeaderFilter.java

@@ -1,15 +0,0 @@
-package io.quarkus.benchmark.filter;
-
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerResponseContext;
-import javax.ws.rs.container.ContainerResponseFilter;
-import javax.ws.rs.ext.Provider;
-
-@Provider
-public class ServerHeaderFilter implements ContainerResponseFilter {
-
-    @Override
-    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
-        responseContext.getHeaders().add("Server", "Quarkus");
-    }
-}