Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The microbenchmarks have been added in a new Play subproject called Play-Microbenchmark. The microbenchmarks are executed using JMH via the sbt-jmh plugin. They can be run with the `jmh:run` command. I've added a few simple benchmarks to show how they are implemented.
- Loading branch information
1 parent
650f3fd
commit 36f183c
Showing
9 changed files
with
229 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
...src/play-microbenchmark/src/main/scala/play/api/mvc/Cookies_01_ReadCookieFromHeader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package play.api.mvc | ||
|
||
import org.openjdk.jmh.annotations._ | ||
|
||
/** | ||
* This benchmark reads a cookie value from a RequestHeader. | ||
*/ | ||
@State(Scope.Benchmark) | ||
class Cookies_01_ReadCookieFromHeader { | ||
|
||
var requestHeader: RequestHeader = null | ||
var result: String = null | ||
|
||
@Setup(Level.Iteration) | ||
def setup(): Unit = { | ||
requestHeader = MvcHelpers.requestHeader(List( | ||
"Accept-Encoding" -> "gzip, deflate, sdch, br", | ||
"Host" -> "www.playframework.com", | ||
"Accept-Language" -> "en-US,en;q=0.8", | ||
"Upgrade-Insecure-Requests" -> "1", | ||
"User-Agent" -> "Mozilla/9.9 (Macintosh; Intel Mac OS X 10_99_9) AppleWebKit/999.99 (KHTML, like Gecko) Chrome/99.9.9999.999 Safari/999.999", | ||
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", | ||
"Cache-Control" -> "max-age=0", | ||
"Cookie" -> "__utma=99999999999999999999999999999999999999999999999999999; __utmz=999999999999999999999999999999999999999999999999999999999999999999999; _mkto_trk=999999999999999999999999999999999999999999999999999999999999999", | ||
"Connection" -> "keep-alive" | ||
)) | ||
result = null | ||
} | ||
|
||
@TearDown(Level.Iteration) | ||
def tearDown(): Unit = { | ||
// Check the benchmark got the correct result | ||
assert(result == "99999999999999999999999999999999999999999999999999999") | ||
} | ||
|
||
@Benchmark | ||
def getSomeCookie(): Unit = { | ||
result = requestHeader.cookies.get("__utma").get.value | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
framework/src/play-microbenchmark/src/main/scala/play/api/mvc/MvcHelpers.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package play.api.mvc | ||
|
||
import org.openjdk.jmh.annotations.{ Level, Setup } | ||
import play.core.server.netty.NettyHelpers | ||
|
||
object MvcHelpers { | ||
def requestHeader(headerList: List[(String, String)]): RequestHeader = { | ||
val rawRequest = NettyHelpers.nettyRequest(headers = headerList) | ||
NettyHelpers.conversion.convertRequest(1L, NettyHelpers.localhost, None, rawRequest).get | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...rc/play-microbenchmark/src/main/scala/play/api/mvc/RequestHeader_01_ReadHeaderValue.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package play.api.mvc | ||
|
||
import org.openjdk.jmh.annotations._ | ||
|
||
/** | ||
* This benchmark reads a header from a RequestHeader object. | ||
*/ | ||
@State(Scope.Benchmark) | ||
class RequestHeader_01_ReadHeaderValue { | ||
|
||
var requestHeader: RequestHeader = null | ||
var result: String = null | ||
|
||
@Setup(Level.Iteration) | ||
def setup(): Unit = { | ||
requestHeader = MvcHelpers.requestHeader(List( | ||
"Accept-Encoding" -> "gzip, deflate, sdch, br", | ||
"Host" -> "www.playframework.com", | ||
"Accept-Language" -> "en-US,en;q=0.8", | ||
"Upgrade-Insecure-Requests" -> "1", | ||
"User-Agent" -> "Mozilla/9.9 (Macintosh; Intel Mac OS X 10_99_9) AppleWebKit/999.99 (KHTML, like Gecko) Chrome/99.9.9999.999 Safari/999.999", | ||
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", | ||
"Cache-Control" -> "max-age=0", | ||
"Cookie" -> "__utma=99999999999999999999999999999999999999999999999999999; __utmz=999999999999999999999999999999999999999999999999999999999999999999999; _mkto_trk=999999999999999999999999999999999999999999999999999999999999999", | ||
"Connection" -> "keep-alive" | ||
)) | ||
result = null | ||
} | ||
|
||
@TearDown(Level.Iteration) | ||
def tearDown(): Unit = { | ||
// Check the benchmark got the correct result | ||
assert(result == "max-age=0") | ||
} | ||
|
||
@Benchmark | ||
def getCacheControlHeader(): Unit = { | ||
result = requestHeader.headers("Cache-Control") | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
framework/src/play-microbenchmark/src/main/scala/play/core/server/netty/NettyHelpers.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package play.core.server.netty | ||
|
||
import java.net.InetSocketAddress | ||
|
||
import io.netty.handler.codec.http.{ DefaultHttpRequest, HttpMethod, HttpRequest, HttpVersion } | ||
import play.core.server.common.ForwardedHeaderHandler | ||
|
||
object NettyHelpers { | ||
|
||
val conversion: NettyModelConversion = new NettyModelConversion( | ||
new ForwardedHeaderHandler(ForwardedHeaderHandler.ForwardedHeaderHandlerConfig(None)) | ||
) | ||
|
||
val localhost: InetSocketAddress = new InetSocketAddress("127.0.0.1", 9999) | ||
|
||
def nettyRequest( | ||
method: String = "GET", | ||
target: String = "/", | ||
headers: List[(String, String)] = Nil): HttpRequest = { | ||
val r = new DefaultHttpRequest(HttpVersion.valueOf("HTTP/1.1"), HttpMethod.valueOf(method), target) | ||
for ((name, value) <- headers) { | ||
r.headers().add(name, value) | ||
} | ||
r | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...src/main/scala/play/core/server/netty/NettyModelConversion_01_ConvertMinimalRequest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package play.core.server.netty | ||
|
||
import io.netty.handler.codec.http.HttpRequest | ||
import org.openjdk.jmh.annotations.{ TearDown, _ } | ||
import play.api.mvc.RequestHeader | ||
|
||
import scala.util.Try | ||
|
||
@State(Scope.Benchmark) | ||
class NettyModelConversion_01_ConvertMinimalRequest { | ||
|
||
// Cache some values that will be used in the benchmark | ||
private val conversion = NettyHelpers.conversion | ||
private val remoteAddress = NettyHelpers.localhost | ||
|
||
// Benchmark state | ||
private var request: HttpRequest = null | ||
private var result: RequestHeader = null | ||
|
||
@Setup(Level.Iteration) | ||
def setup(): Unit = { | ||
request = NettyHelpers.nettyRequest( | ||
method = "GET", | ||
target = "/", | ||
headers = Nil | ||
) | ||
result = null | ||
} | ||
|
||
@TearDown(Level.Iteration) | ||
def tearDown(): Unit = { | ||
// Sanity check the benchmark result | ||
assert(result.path == "/") | ||
} | ||
|
||
@Benchmark | ||
def convertRequest(): Unit = { | ||
result = conversion.convertRequest(1L, remoteAddress, None, request).get | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
.../src/main/scala/play/core/server/netty/NettyModelConversion_02_ConvertNormalRequest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package play.core.server.netty | ||
|
||
import io.netty.handler.codec.http.HttpRequest | ||
import org.openjdk.jmh.annotations.{ TearDown, _ } | ||
import play.api.mvc.RequestHeader | ||
|
||
@State(Scope.Benchmark) | ||
class NettyModelConversion_02_ConvertNormalRequest { | ||
|
||
// Cache some values that will be used in the benchmark | ||
private val conversion = NettyHelpers.conversion | ||
private val remoteAddress = NettyHelpers.localhost | ||
|
||
// Benchmark state | ||
private var request: HttpRequest = null | ||
private var result: RequestHeader = null | ||
|
||
@Setup(Level.Iteration) | ||
def setup(): Unit = { | ||
request = NettyHelpers.nettyRequest( | ||
method = "GET", | ||
target = "/x/y/z", | ||
headers = List( | ||
"Accept-Encoding" -> "gzip, deflate, sdch, br", | ||
"Host" -> "www.playframework.com", | ||
"Accept-Language" -> "en-US,en;q=0.8", | ||
"Upgrade-Insecure-Requests" -> "1", | ||
"User-Agent" -> "Mozilla/9.9 (Macintosh; Intel Mac OS X 10_99_9) AppleWebKit/999.99 (KHTML, like Gecko) Chrome/99.9.9999.999 Safari/999.999", | ||
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", | ||
"Cache-Control" -> "max-age=0", | ||
"Cookie" -> "__utma=99999999999999999999999999999999999999999999999999999; __utmz=999999999999999999999999999999999999999999999999999999999999999999999; _mkto_trk=999999999999999999999999999999999999999999999999999999999999999", | ||
"Connection" -> "keep-alive" | ||
) | ||
) | ||
result = null | ||
} | ||
|
||
@TearDown(Level.Iteration) | ||
def tearDown(): Unit = { | ||
// Sanity check the benchmark result | ||
assert(result.path == "/x/y/z") | ||
} | ||
|
||
@Benchmark | ||
def convertRequest(): Unit = { | ||
result = conversion.convertRequest(1L, remoteAddress, None, request).get | ||
} | ||
} |