瀏覽代碼

Play2 enhancements (#4671)

* Upgrade to Play 2.7.1

* Revert "Play2: Use thread-pool-executor for all database benchmarks"

This reverts commit 0fcdb3509357158d30430f2abb07bbce372b1384.

* Let's try parallelism-max = 64

* Update dependency for reactivemongo

* Play 2.7.2 released meanwhile

* Use snapshots of play-reactivemongo for now
Matthias Kurz 6 年之前
父節點
當前提交
547370f416
共有 22 個文件被更改,包括 209 次插入179 次删除
  1. 43 26
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/controllers/Application.java
  2. 5 11
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf
  3. 1 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt
  4. 53 44
      frameworks/Java/play2-java/play2-java-jooq-hikaricp/app/controllers/Application.java
  5. 5 11
      frameworks/Java/play2-java/play2-java-jooq-hikaricp/conf/application.conf
  6. 1 1
      frameworks/Java/play2-java/play2-java-jooq-hikaricp/project/plugins.sbt
  7. 37 27
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java
  8. 5 11
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  9. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  10. 4 3
      frameworks/Java/play2-java/play2-java/conf/application.conf
  11. 1 1
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  12. 23 13
      frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala
  13. 5 3
      frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/DbOperation.scala
  14. 5 11
      frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf
  15. 1 1
      frameworks/Scala/play2-scala/play2-scala-anorm/project/plugins.sbt
  16. 4 2
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/build.sbt
  17. 4 3
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/application.conf
  18. 1 1
      frameworks/Scala/play2-scala/play2-scala-reactivemongo/project/plugins.sbt
  19. 4 3
      frameworks/Scala/play2-scala/play2-scala-slick/conf/application.conf
  20. 1 1
      frameworks/Scala/play2-scala/play2-scala-slick/project/plugins.sbt
  21. 4 3
      frameworks/Scala/play2-scala/play2-scala/conf/application.conf
  22. 1 1
      frameworks/Scala/play2-scala/play2-scala/project/plugins.sbt

+ 43 - 26
frameworks/Java/play2-java/play2-java-ebean-hikaricp/app/controllers/Application.java

@@ -4,41 +4,56 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ThreadLocalRandom;
 
+import javax.inject.Inject;
+
 import models.Fortune;
 import models.World;
 import play.libs.Json;
 import play.mvc.Controller;
 import play.mvc.Result;
+import utils.DatabaseExecutionContext;
 
 public class Application extends Controller {
 
-    public Result db() {
-        return ok(Json.toJson(getRandomWorlds(1).get(0)));
+    private final DatabaseExecutionContext dbEc;
+
+    @Inject
+    public Application(final DatabaseExecutionContext dbEc) {
+        this.dbEc = dbEc;
+    }
+
+    public CompletionStage<Result> db() {
+        return getRandomWorlds(1).thenApply(worlds -> ok(Json.toJson(worlds.get(0))));
     }
 
-    public Result queries(final String queries) {
-        return ok(Json.toJson(getRandomWorlds(queryCount(queries))));
+    public CompletionStage<Result> queries(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(Json.toJson(worlds)));
     }
 
-    public Result fortunes() {
-        final List<Fortune> fortunes = Fortune.findAll();
-        fortunes.add(new Fortune("Additional fortune added at request time."));
-        Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
+    public CompletionStage<Result> fortunes() {
+        return CompletableFuture.supplyAsync(() -> {
+            final List<Fortune> fortunes = Fortune.findAll();
+            fortunes.add(new Fortune("Additional fortune added at request time."));
+            Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
 
-        return ok(views.html.fortunes.render(fortunes));
+            return ok(views.html.fortunes.render(fortunes));
+        }, dbEc);
     }
 
-    public Result update(final String queries) {
-        final List<World> worlds = getRandomWorlds(queryCount(queries));
-        final Random random = ThreadLocalRandom.current();
-        for (final World world : worlds) {
-            world.randomNumber = (long) (random.nextInt(10000) + 1);
-        }
+    public CompletionStage<Result> update(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
+            final Random random = ThreadLocalRandom.current();
+            for (final World world : worlds) {
+                world.randomNumber = (long) (random.nextInt(10000) + 1);
+            }
 
-        final List<World> updatedWorlds = World.save(worlds);
-        return ok(Json.toJson(updatedWorlds));
+            final List<World> updatedWorlds = World.save(worlds);
+            return ok(Json.toJson(updatedWorlds));
+        }, dbEc);
     }
 
     private int queryCount(final String queryCountString) {
@@ -57,15 +72,17 @@ public class Application extends Controller {
         return queryCount;
     }
 
-    private List<World> getRandomWorlds(final int n) {
-        final Random random = ThreadLocalRandom.current();
-        final List<World> worlds = new ArrayList<>(n);
-        for (int i = 0; i < n; ++i) {
-            long randomId = random.nextInt(10000) + 1;
-            final World world = World.find(randomId);
-            worlds.add(world);
-        }
-        return worlds;
+    private CompletionStage<List<World>> getRandomWorlds(final int n) {
+        return CompletableFuture.supplyAsync(() -> {
+            final Random random = ThreadLocalRandom.current();
+            final List<World> worlds = new ArrayList<>(n);
+            for (int i = 0; i < n; ++i) {
+                long randomId = random.nextInt(10000) + 1;
+                final World world = World.find(randomId);
+                worlds.add(world);
+            }
+            return worlds;
+        }, dbEc);
     }
 
 }

+ 5 - 11
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf

@@ -41,7 +41,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -50,8 +50,6 @@ play.server {
 akka {
   actor {
     default-dispatcher {
-      executor = "thread-pool-executor"
-
       fork-join-executor {
         # one thread per core is enough
         # https://github.com/playframework/playframework/issues/7242#issuecomment-295215448
@@ -59,22 +57,18 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }
 
-      # https://www.playframework.com/documentation/2.7.x/ThreadPools#Highly-synchronous
-      thread-pool-executor {
-        fixed-pool-size = 44 # db conn pool (29) + number of cores (14) + housekeeping (1)
-      }
-
       # https://doc.akka.io/docs/akka/2.5.11/dispatchers.html#looking-up-a-dispatcher
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
       # Set to 1 for as fair as possible.
-      throughput = 1
+      throughput = 64
     }
   }
 }

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt

@@ -1,3 +1,3 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")
 
 addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "5.0.1")

+ 53 - 44
frameworks/Java/play2-java/play2-java-jooq-hikaricp/app/controllers/Application.java

@@ -7,6 +7,8 @@ import static play.mvc.Http.MimeTypes.JSON;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ThreadLocalRandom;
 
 import javax.inject.Inject;
@@ -23,6 +25,7 @@ import models.tables.records.WorldRecord;
 import play.db.Database;
 import play.mvc.Controller;
 import play.mvc.Result;
+import utils.DatabaseExecutionContext;
 
 public class Application extends Controller {
 
@@ -30,49 +33,53 @@ public class Application extends Controller {
     private static final JSONFormat JSON_FORMAT = JSONFormat.DEFAULT_FOR_RECORDS.recordFormat(RecordFormat.OBJECT);
 
     private final Database db;
+    private final DatabaseExecutionContext dbEc;
 
     @Inject
-    public Application(final Database db) {
+    public Application(final Database db, final DatabaseExecutionContext dbEc) {
         this.db = db;
+        this.dbEc = dbEc;
     }
 
-    public Result db() {
-        return ok(getRandomWorlds(1).get(0).formatJSON(JSON_FORMAT)).as(JSON);
+    public CompletionStage<Result> db() {
+        return getRandomWorlds(1).thenApply(worlds -> ok(worlds.get(0).formatJSON(JSON_FORMAT)).as(JSON));
     }
 
-    public Result queries(final String queries) {
-        return ok(getRandomWorlds(queryCount(queries)).formatJSON(JSON_FORMAT)).as(JSON);
+    public CompletionStage<Result> queries(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(worlds.formatJSON(JSON_FORMAT)).as(JSON));
     }
 
-    public Result fortunes() {
-        final List<FortuneRecord> fortunes = this.db.withConnection(connection -> {
-            return DSL.using(connection, DIALECT).select(FORTUNE.ID, FORTUNE.MESSAGE).from(FORTUNE).fetchInto(FortuneRecord.class);
-        });
-        fortunes.add(new FortuneRecord(UInteger.valueOf(0), "Additional fortune added at request time."));
-        Collections.sort(fortunes, (f1, f2) -> f1.getMessage().compareTo(f2.getMessage()));
+    public CompletionStage<Result> fortunes() {
+        return CompletableFuture.supplyAsync(() -> {
+            final List<FortuneRecord> fortunes = this.db.withConnection(connection -> {
+                return DSL.using(connection, DIALECT).select(FORTUNE.ID, FORTUNE.MESSAGE).from(FORTUNE).fetchInto(FortuneRecord.class);
+            });
+            fortunes.add(new FortuneRecord(UInteger.valueOf(0), "Additional fortune added at request time."));
+            Collections.sort(fortunes, (f1, f2) -> f1.getMessage().compareTo(f2.getMessage()));
 
-        return ok(views.html.fortunes.render(fortunes));
+            return ok(views.html.fortunes.render(fortunes));
+        }, dbEc);
     }
 
-    public Result update(final String queries) {
-        final org.jooq.Result<WorldRecord> worlds =  getRandomWorlds(queryCount(queries));
-
-        final Random random = ThreadLocalRandom.current();
-        for (final WorldRecord world : worlds) {
-            world.setRandomnumber((random.nextInt(10000) + 1));
-        }
-
-        final int batchSize = 25;
-        final int batches = ((worlds.size() / batchSize) + 1);
-        this.db.withConnection(connection -> {
-            final DSLContext sql = DSL.using(connection, DIALECT);
-            for ( int i = 0 ; i < batches ; ++i ) {
-                sql.batchUpdate(worlds.subList(i * batchSize, Math.min((i + 1) * batchSize, worlds.size()))).execute();
+    public CompletionStage<Result> update(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
+            final Random random = ThreadLocalRandom.current();
+            for (final WorldRecord world : worlds) {
+                world.setRandomnumber((random.nextInt(10000) + 1));
             }
-            return null;
-        });
 
-        return ok(worlds.formatJSON(JSON_FORMAT)).as(JSON);
+            final int batchSize = 25;
+            final int batches = ((worlds.size() / batchSize) + 1);
+            this.db.withConnection(connection -> {
+                final DSLContext sql = DSL.using(connection, DIALECT);
+                for ( int i = 0 ; i < batches ; ++i ) {
+                    sql.batchUpdate(worlds.subList(i * batchSize, Math.min((i + 1) * batchSize, worlds.size()))).execute();
+                }
+                return null;
+            });
+
+            return ok(worlds.formatJSON(JSON_FORMAT)).as(JSON);
+        }, dbEc);
     }
 
     private int queryCount(final String queryCountString) {
@@ -91,22 +98,24 @@ public class Application extends Controller {
         return queryCount;
     }
 
-    private org.jooq.Result<WorldRecord> getRandomWorlds(final int n) {
-        final Random random = ThreadLocalRandom.current();
-        org.jooq.Result<WorldRecord> worlds = null;
-        for (int i = 0; i < n; ++i) {
-            long randomId = random.nextInt(10000) + 1;
-            final org.jooq.Result<WorldRecord> world = this.db.withConnection(connection -> {
-                return DSL.using(connection, DIALECT).selectFrom(WORLD).where(WORLD.ID.eq(UInteger.valueOf(randomId))).fetch();
-            });
-
-            if(worlds == null) {
-                worlds = world;
-            } else {
-                worlds.add(world.get(0));
+    private CompletionStage<org.jooq.Result<WorldRecord>> getRandomWorlds(final int n) {
+        return CompletableFuture.supplyAsync(() -> {
+            final Random random = ThreadLocalRandom.current();
+            org.jooq.Result<WorldRecord> worlds = null;
+            for (int i = 0; i < n; ++i) {
+                long randomId = random.nextInt(10000) + 1;
+                final org.jooq.Result<WorldRecord> world = this.db.withConnection(connection -> {
+                    return DSL.using(connection, DIALECT).selectFrom(WORLD).where(WORLD.ID.eq(UInteger.valueOf(randomId))).fetch();
+                });
+
+                if(worlds == null) {
+                    worlds = world;
+                } else {
+                    worlds.add(world.get(0));
+                }
             }
-        }
-        return worlds;
+            return worlds;
+        }, dbEc);
     }
 
 }

+ 5 - 11
frameworks/Java/play2-java/play2-java-jooq-hikaricp/conf/application.conf

@@ -41,7 +41,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -50,8 +50,6 @@ play.server {
 akka {
   actor {
     default-dispatcher {
-      executor = "thread-pool-executor"
-
       fork-join-executor {
         # one thread per core is enough
         # https://github.com/playframework/playframework/issues/7242#issuecomment-295215448
@@ -59,22 +57,18 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }
 
-      # https://www.playframework.com/documentation/2.7.x/ThreadPools#Highly-synchronous
-      thread-pool-executor {
-        fixed-pool-size = 44 # db conn pool (29) + number of cores (14) + housekeeping (1)
-      }
-
       # https://doc.akka.io/docs/akka/2.5.11/dispatchers.html#looking-up-a-dispatcher
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
       # Set to 1 for as fair as possible.
-      throughput = 1
+      throughput = 64
     }
   }
 }

+ 1 - 1
frameworks/Java/play2-java/play2-java-jooq-hikaricp/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 37 - 27
frameworks/Java/play2-java/play2-java-jpa-hikaricp/app/controllers/Application.java

@@ -4,6 +4,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ThreadLocalRandom;
 
 import javax.inject.Inject;
@@ -14,41 +16,47 @@ import play.db.jpa.JPAApi;
 import play.libs.Json;
 import play.mvc.Controller;
 import play.mvc.Result;
+import utils.DatabaseExecutionContext;
 
 public class Application extends Controller {
 
     private final JPAApi jpa;
+    private final DatabaseExecutionContext dbEc;
 
     @Inject
-    public Application(final JPAApi jpa) {
+    public Application(final JPAApi jpa, final DatabaseExecutionContext dbEc) {
         this.jpa = jpa;
+        this.dbEc = dbEc;
     }
 
-    public Result db() {
-        return ok(Json.toJson(getRandomWorlds(1).get(0)));
+    public CompletionStage<Result> db() {
+        return getRandomWorlds(1).thenApply(worlds -> ok(Json.toJson(worlds.get(0))));
     }
 
-    public Result queries(final String queries) {
-        return ok(Json.toJson(getRandomWorlds(queryCount(queries))));
+    public CompletionStage<Result> queries(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApply(worlds -> ok(Json.toJson(worlds)));
     }
 
-    public Result fortunes() {
-        final List<Fortune> fortunes = Fortune.findAll(this.jpa);
-        fortunes.add(new Fortune("Additional fortune added at request time."));
-        Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
+    public CompletionStage<Result> fortunes() {
+        return CompletableFuture.supplyAsync(() -> {
+            final List<Fortune> fortunes = Fortune.findAll(this.jpa);
+            fortunes.add(new Fortune("Additional fortune added at request time."));
+            Collections.sort(fortunes, (f1, f2) -> f1.message.compareTo(f2.message));
 
-        return ok(views.html.fortunes.render(fortunes));
+            return ok(views.html.fortunes.render(fortunes));
+        }, dbEc);
     }
 
-    public Result update(final String queries) {
-        final List<World> worlds = getRandomWorlds(queryCount(queries));
-        final Random random = ThreadLocalRandom.current();
-        for (final World world : worlds) {
-            world.randomNumber = (long) (random.nextInt(10000) + 1);
-        }
+    public CompletionStage<Result> update(final String queries) {
+        return getRandomWorlds(queryCount(queries)).thenApplyAsync(worlds -> {
+            final Random random = ThreadLocalRandom.current();
+            for (final World world : worlds) {
+                world.randomNumber = (long) (random.nextInt(10000) + 1);
+            }
 
-        final List<World> updatedWorlds = World.save(worlds, this.jpa);
-        return ok(Json.toJson(updatedWorlds));
+            final List<World> updatedWorlds = World.save(worlds, this.jpa);
+            return ok(Json.toJson(updatedWorlds));
+        }, dbEc);
     }
 
     private int queryCount(final String queryCountString) {
@@ -67,15 +75,17 @@ public class Application extends Controller {
         return queryCount;
     }
 
-    private List<World> getRandomWorlds(final int n) {
-        final Random random = ThreadLocalRandom.current();
-        final List<World> worlds = new ArrayList<>(n);
-        for (int i = 0; i < n; ++i) {
-            long randomId = random.nextInt(10000) + 1;
-            final World world = World.findById(randomId, this.jpa);
-            worlds.add(world);
-        }
-        return worlds;
+    private CompletionStage<List<World>> getRandomWorlds(final int n) {
+        return CompletableFuture.supplyAsync(() -> {
+            final Random random = ThreadLocalRandom.current();
+            final List<World> worlds = new ArrayList<>(n);
+            for (int i = 0; i < n; ++i) {
+                long randomId = random.nextInt(10000) + 1;
+                final World world = World.findById(randomId, this.jpa);
+                worlds.add(world);
+            }
+            return worlds;
+        }, dbEc);
     }
 
 }

+ 5 - 11
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -41,7 +41,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -50,8 +50,6 @@ play.server {
 akka {
   actor {
     default-dispatcher {
-      executor = "thread-pool-executor"
-
       fork-join-executor {
         # one thread per core is enough
         # https://github.com/playframework/playframework/issues/7242#issuecomment-295215448
@@ -59,22 +57,18 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }
 
-      # https://www.playframework.com/documentation/2.7.x/ThreadPools#Highly-synchronous
-      thread-pool-executor {
-        fixed-pool-size = 44 # db conn pool (29) + number of cores (14) + housekeeping (1)
-      }
-
       # https://doc.akka.io/docs/akka/2.5.11/dispatchers.html#looking-up-a-dispatcher
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
       # Set to 1 for as fair as possible.
-      throughput = 1
+      throughput = 64
     }
   }
 }

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 4 - 3
frameworks/Java/play2-java/play2-java/conf/application.conf

@@ -41,7 +41,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -57,8 +57,9 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }

+ 1 - 1
frameworks/Java/play2-java/play2-java/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 23 - 13
frameworks/Scala/play2-scala/play2-scala-anorm/app/controllers/Application.scala

@@ -3,26 +3,28 @@ package controllers
 import javax.inject.{Inject, Singleton}
 
 import play.api.mvc._
+import play.mvc.Http
 import play.api.libs.json.Json
 import java.util.concurrent._
 import models.{WorldDAO, FortunesDAO, World, Fortune}
 import utils.DbOperation
+import scala.concurrent.{Future, ExecutionContext}
 
 @Singleton()
-class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOperation: DbOperation, val controllerComponents: ControllerComponents)
+class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOperation: DbOperation, val controllerComponents: ControllerComponents)(implicit ec: ExecutionContext)
   extends BaseController {
 
-  def getRandomWorlds(n: Int): Seq[World] = dbOperation.syncDbOp { implicit connection =>
+  def getRandomWorlds(n: Int): Future[Seq[World]] = dbOperation.asyncDbOp { implicit connection =>
     for (_ <- 1 to n) yield {
       worldDAO.findById(getNextRandom)
     }
   }
 
-  def getFortunes: Seq[Fortune] = dbOperation.syncDbOp { implicit connection =>
+  def getFortunes: Future[Seq[Fortune]] = dbOperation.asyncDbOp { implicit connection =>
     fortunesDAO.getAll
   }
 
-  def updateWorlds(n: Int): Seq[World] = dbOperation.syncDbOp { implicit connection =>
+  def updateWorlds(n: Int): Future[Seq[World]] = dbOperation.asyncDbOp { implicit connection =>
     for(_ <- 1 to n) yield {
       val world = worldDAO.findById(getNextRandom)
       val updatedWorld = world.copy(randomNumber = getNextRandom)
@@ -42,23 +44,31 @@ class Application @Inject() (fortunesDAO: FortunesDAO, worldDAO: WorldDAO, dbOpe
 
   import models.WorldJsonHelpers.toJson
 
-  def db = Action {
-    Ok(Json.toJson(getRandomWorlds(1).head))
+  def db = Action.async {
+    getRandomWorlds(1).map { worlds =>
+      Ok(Json.toJson(worlds.head))
+    }
   }
 
-  def queries(countString: String) = Action {
+  def queries(countString: String) = Action.async {
     val n = parseCount(countString)
-    Ok(Json.toJson(getRandomWorlds(n)))
+    getRandomWorlds(n).map { worlds =>
+      Ok(Json.toJson(worlds))
+    }
   }
 
-  def fortunes() = Action {
-    val appendedFortunes =  Fortune(0, "Additional fortune added at request time.") :: getFortunes.to[List]
-    Ok(views.html.fortune(appendedFortunes))
+  def fortunes() = Action.async {
+    getFortunes.map { dbFortunes =>
+      val appendedFortunes =  Fortune(0, "Additional fortune added at request time.") :: dbFortunes.to[List]
+      Ok(views.html.fortune(appendedFortunes))
+    }
   }
 
-  def update(queries: String) = Action {
+  def update(queries: String) = Action.async {
     val n = parseCount(queries)
-    Ok(Json.toJson(updateWorlds(n)))
+    updateWorlds(n).map { worlds =>
+      Ok(Json.toJson(worlds))
+    }
   }
 
   private def parseCount(s: String): Int = {

+ 5 - 3
frameworks/Scala/play2-scala/play2-scala-anorm/app/utils/DbOperation.scala

@@ -12,18 +12,20 @@ import scala.concurrent.Future
 
 @Singleton
 class DbOperation @Inject() (protected val db: Database,
-  configuration: Configuration) {
+  configuration: Configuration, dbEc: DatabaseExecutionContext) {
 
   /**
    * Run a DB operation in the DB context.
    */
-  def syncDbOp[T](op: Connection => T): T = {
+  def asyncDbOp[T](op: Connection => T): Future[T] = {
     // If the thread-pool queue used by the database grows too large then our server
     // is probably struggling, and we should start dropping requests. If we don't
     // then we'll just slow everything down and it will fail anyway. Better to fail
     // quickly rather than slowly. Set the max size of our queue something above the
     // number of concurrent connections that we expect to be handling.
-    db.withConnection { connection => op(connection) }
+    Future {
+      db.withConnection { connection => op(connection) }
+    }(dbEc)
   }
 
 }

+ 5 - 11
frameworks/Scala/play2-scala/play2-scala-anorm/conf/application.conf

@@ -36,7 +36,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -45,8 +45,6 @@ play.server {
 akka {
   actor {
     default-dispatcher {
-      executor = "thread-pool-executor"
-
       fork-join-executor {
         # one thread per core is enough
         # https://github.com/playframework/playframework/issues/7242#issuecomment-295215448
@@ -54,22 +52,18 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }
 
-      # https://www.playframework.com/documentation/2.7.x/ThreadPools#Highly-synchronous
-      thread-pool-executor {
-        fixed-pool-size = 44 # db conn pool (29) + number of cores (14) + housekeeping (1)
-      }
-
       # https://doc.akka.io/docs/akka/2.5.11/dispatchers.html#looking-up-a-dispatcher
       # Throughput defines the maximum number of messages to be
       # processed per actor before the thread jumps to the next actor.
       # Set to 1 for as fair as possible.
-      throughput = 1
+      throughput = 64
     }
   }
 }

+ 1 - 1
frameworks/Scala/play2-scala/play2-scala-anorm/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 4 - 2
frameworks/Scala/play2-scala/play2-scala-reactivemongo/build.sbt

@@ -6,9 +6,11 @@ lazy val root = (project in file(".")).enablePlugins(PlayScala, PlayNettyServer)
 
 scalaVersion := "2.12.8"
 
+resolvers += Resolver.sonatypeRepo("snapshots")
+
 libraryDependencies ++= Seq(
-  "org.reactivemongo" %% "play2-reactivemongo" % "0.16.2-play27",
-  "org.reactivemongo" %% "reactivemongo-play-json" % "0.16.2-play27",
+  "org.reactivemongo" %% "play2-reactivemongo" % "0.17.0-play27-SNAPSHOT",
+  "org.reactivemongo" %% "reactivemongo-play-json" % "0.17.0-play27-SNAPSHOT",
   "com.softwaremill.macwire" %% "macros" % "2.3.0",
   "com.softwaremill.macwire" %% "util" % "2.3.0"
 )

+ 4 - 3
frameworks/Scala/play2-scala/play2-scala-reactivemongo/conf/application.conf

@@ -32,7 +32,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -48,8 +48,9 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }

+ 1 - 1
frameworks/Scala/play2-scala/play2-scala-reactivemongo/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 4 - 3
frameworks/Scala/play2-scala/play2-scala-slick/conf/application.conf

@@ -36,7 +36,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -52,8 +52,9 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }

+ 1 - 1
frameworks/Scala/play2-scala/play2-scala-slick/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")

+ 4 - 3
frameworks/Scala/play2-scala/play2-scala/conf/application.conf

@@ -36,7 +36,7 @@ play.server {
         # The default is 1 since Linux Kernel 3.13
         # You can check via "cat /proc/sys/net/ipv4/tcp_fastopen"
         # However 3 would be better, but we can't change it to that value because we don't have root permission when running the benchmarks
-        TCP_FASTOPEN = 1
+        "io.netty.channel.epoll.EpollChannelOption#TCP_FASTOPEN" = 1
       }
     }
   }
@@ -52,8 +52,9 @@ akka {
 
         # Information about the TechEmpower benchmark environment: https://www.techempower.com/benchmarks/#section=environment
         # The environment variable physical_cpu_count does NOT include the hyperthreaded cores!
-        parallelism-max = 14
-        parallelism-max = ${?thread_count}
+        #parallelism-max = 14
+        #parallelism-max = ${?thread_count}
+        parallelism-max = 64
 
         task-peeking-mode="LIFO" # based on https://www.playframework.com/documentation/2.7.x/Migration24#Thread-pool-configuration
       }

+ 1 - 1
frameworks/Scala/play2-scala/play2-scala/project/plugins.sbt

@@ -1 +1 @@
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")