scala - Simple play/scala benchmark, rendering a view versus a raw text output comparison
问题描述
I was just benchmarking a new play/scala application.
When performing a simple text output in my action, I get 60K requests per second.
If I render a view (see below), it drops to 13K per second. Since views are just functions in scala, I would have expected that the extra overhead of calling a function wouldn't drop the requests per second down so dramatically.
I only ran the benchmark for 10-30 seconds, would it take longer for the jvm to optimize maybe or this is just expected behavour?
def index() = Action { implicit request: Request[AnyContent] =>
Ok("hello")
}
If I actually render a view, the requests per second drops to about 13K.
def index() = Action { implicit request: Request[AnyContent] =>
Ok(views.html.index())
}
/app/views/index.scala.html
@()
@main("Welcome to Play") {
<h1>Welcome to Play!</h1>
}
/app/views/main.scala.html
@*
* This template is called from the `index` template. This template
* handles the rendering of the page header and body tags. It takes
* two arguments, a `String` for the title of the page and an `Html`
* object to insert into the body of the page.
*@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
@* Here's where we render the page title `String`. *@
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
</head>
<body>
@* And here's where we render the `Html` object containing
* the page content. *@
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>
解决方案
正如我在评论中已经说过的那样,视图不是一个微不足道的功能。它执行字符串连接,并且还调用routes.Assets.versioned
了 3 次。分析会话显示,视图基本上只等待这个函数:
深入研究,我们了解到该versioned
函数总是从类路径中重新读取文件:
也许您可以打开一个问题并询问 Play 框架创建者,是否可以更好地优化资产服务?
编辑:我分析了两个设置。首先我修改了HomeControllerSpec
测试:
"render the index page from a new instance of controller" in {
val controller = new HomeController(stubControllerComponents())
val indexAction = controller.index()
val fakeRequest = FakeRequest(GET, "/")
var i = 100000
while (i > 0) {
indexAction.apply(fakeRequest)
i -= 1
}
但这并不排除某些组件在生产模式下的行为会有所不同。因此,我运行sbt stage
并启动了生成的应用程序,将分析器附加到正在运行的 JVM,并对分析的 JVM 执行了 10000 个请求。结果是一样的。
推荐阅读
- python - 编写函数时是否有必要(在 Python 2.7 中)为全局变量创建参数?
- tableau-api - 在画面中查找总计
- python-3.x - 如何从字典列表中提取特定值?
- php - 从 HTML 表单中获取日期值并在 PHP 中传递
- haskell - 构造从所有参数构建异构列表的函数
- vba - 将用户窗体 (VBA) 转换为 exe
- xslt - FO:XSL 上的动态列数量
- android - MotionLayout 以编程方式跳转到结束 ConstraintSet
- vue.js - Vue-bootstrap如何实现我的popover的流畅工作
- mysql - vb.net backgroundworker 与 mysql 阅读器到多个文本框