Play Framework: Explain Performance

I tried to tweak the Java Framework Framework sample application (version 2.2.2) to test its performance against some simple use cases I had in mind. Here's what I did:

Play controller

I wrote a basic application controller to test the performance of a custom library that I wanted to use in both sync scripts and async:

public class Application extends Controller {
    public static JsonNode transform(Request request) {
        // this method reads a json from request, applies some transformation and returns a new JsonNode
    }

    public static Result syncTest() {
        JsonNode node = transform(request());
            if(node.has("error")) {
                return badRequest(node);
            } else {
                return ok(node);
            }       
        }

        public static Promise<Result> asyncTest() {
            final Request request = request();
                    Promise<JsonNode> promise = Promise.promise(
                        new Function0<JsonNode>() {
                                public JsonNode apply() {
                            return transform(request);
                                }
                    });

            return promise.map(new Function<JsonNode, Result> () {
            public Result apply(JsonNode node) {
                if(node.has("error")) {
                    return badRequest(node);
                } else {
                    return ok(node);
                }
            }
        });
    } 
}

      

I am running this service in a VM running on Azure with 2 2.0ghz cores and 3.4GB of RAM.

Testing

I used wrk from another computer to run tests on both sync routes and async routes. These are the commands and results I got:

./wrk -s post.lua -d30s -c100 -t10 --latency http://my.proxy.net:8080/syncTest

Running 30s test @ 
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    84.98ms   48.13ms 410.73ms   68.95%
    Req/Sec   121.23     18.90   181.00     73.67%
  Latency Distribution
     50%   81.36ms
     75%  112.51ms
     90%  144.44ms
     99%  231.99ms
  36362 requests in 30.03s, 10.99MB read
Requests/sec:   1210.80
Transfer/sec:    374.83KB

      

./wrk -s post.lua -d30s -c100 -t10 --latency http://my.proxy.net:8080/asyncTest

Running 30s test @ 
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    82.07ms   36.55ms 257.93ms   70.53%
    Req/Sec   122.44     15.39   161.00     73.24%
  Latency Distribution
     50%   80.26ms
     75%  102.37ms
     90%  127.14ms
     99%  187.17ms
  36668 requests in 30.02s, 11.09MB read
Requests/sec:   1221.62
Transfer/sec:    378.18KB

      

./wrk -s post.lua -d30s -c1000 -t10 --latency http://my.proxy.net:8080/syncTest

Running 30s test @ 
  10 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   842.98ms  617.40ms   4.18s    59.56%
    Req/Sec   118.02     16.82   174.00     77.50%
  Latency Distribution
     50%  837.67ms
     75%    1.14s 
     90%    1.71s 
     99%    2.51s 
  35326 requests in 30.01s, 10.68MB read
  Socket errors: connect 0, read 27, write 0, timeout 181
Requests/sec:   1176.97
Transfer/sec:    364.35KB

      

./wrk -s post.lua -d30s -c1000 -t10 --latency http://my.proxy.net:8080/asyncTest

Running 30s test @ 
  10 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.98s     4.53s   17.97s    72.66%
    Req/Sec    21.32     10.45    37.00     59.74%
  Latency Distribution
     50%    4.86s 
     75%    8.30s 
     90%   12.89s 
     99%   17.10s 
  6361 requests in 30.08s, 1.92MB read
  Socket errors: connect 0, read 0, write 0, timeout 8410
Requests/sec:    211.47
Transfer/sec:     65.46KB

      

During all tests, both processors on the server machine were running at 100%. Later, I repeated these experiments, but modified the Promises I created to run in a different execution context than the default. In this case, both synchronous and asynchronous methods are executed in a very similar way.

Questions

  • Why when using 10 threads with 100 connections, both methods have similar latency and request in seconds.

  • Why, when using 1000 connections, the asynchronous method has the worst performance, which is asynchronous or, in the case of a separate execution context, the same performance for the synchronization methods?

Is it because the conversion method is not really intensive because I did the wrong asynchronous implementation or because I didn't completely understand how this thing is supposed to work?

Thanks in advance!

+3


source to share





All Articles