GoRazor 是 Razor 视图引擎的 Go 语言移植版本。
语法:<div>Hello @strings.ToUpper(req.CurrentUser.Name)</div>
gorazor
应该是go语言的第一个支持将模板编译成为go代码的“预编译式”模板引擎。
采用预编译一个显而易见的好处当然是渲染速度;没想一晃五年过去,go的后端模板引擎居然层出不穷,而相比起后来出现的这些模板,gorazor的渲染速度,赫然是最慢的一个:
QuickTemplate
也有在其FAQ中说gorazor
相比起QuickTemplate
少了性能优化。
QuickTemplate的作者也是fasthttp的作者Aliaksandr Valialkin,后者是go语言中非常有名http服务器实现,比go官方内置的net/http
库快了近10倍。
在研究过QuickTemplate之后,我对其作者valyala采用的优化手段叹为观止,试列举几项如下:
这些优化我感觉其实已经超乎了其模板引擎本身,而是使用在其它go项目中。
赞叹之余,我也不禁在想,gorazor能否借鉴这些来做优化呢?
gorazor渲染慢的主要原因,是因为我提供的全部都是基于string的输入、输出接口;那么,在压测(当然还有实际运行)的时候,必然会有大量的字符串对象被创建、销毁;内存申请多,性能肯定也就慢。
增加StringWriter接口的话,应该可以显著提高性能:
// string 输入/输出接口
func Msg(u *models.User) string {
...
}
// StringWriter接口
func RenderMsg(_buffer io.StringWriter, u *models.User) {
...
}
后者相对于前者,无需创建并返回 string 对象;而是将数据写入 _buffer 中;这样一来,就能够利用缓存池来避免内存分配。
当然,整体接口的改动也意味着需要对gorazor内部的代码生成引擎做大幅修改,特别是goraozr支持layout / helper的嵌套调用;所有内部谢谢嵌套的调用逻辑都需要改。
但,那就改吧~既然是整体接口的大幅修改,那么版本号是可以升级到2.0的。
经过几个月断断续续的修改,2.0版终于完成。因为支持了Writer接口,我实际上也可以直接使用QuickTemplate的bytebufferpool等方式来进行优化性能测试结果,这只需要几行代码:
type quickStringWriter struct {
bb *quicktemplate.ByteBuffer
}
func (q *quickStringWriter) WriteString(s string) (i int, e error) {
return q.bb.Write(unsafeStrToBytes(s))
}
便可直接将quickStringWriter
传递给gorazor模板。
这样一来,gorazor的性能实际上已经不逊于QuickTemplate了,毕竟,压测中性能的主要损耗是在字符串对象的转换以及缓存池的复用。
但gorazor依旧做不到内存的零分配,唯一的一次内存分配是发生在这里:
// HTMLEscape wraps template.HTMLEscapeString
func HTMLEscape(m interface{}) string {
switch v := m.(type) {
case int:
return strconv.Itoa(v)
case string:
return template.HTMLEscapeString(v)
}
s := fmt.Sprint(m)
return template.HTMLEscapeString(s)
}
当在模板中写入变量时,变量的类型很可能是不同的;最常见的当然是有int以及string;不同的类型也需要做不同的处理,可就是这么一句switch v := m.(type) {
类型判断会产生新变量以造成内存分配。
咋看这几乎无解,因为我不可能在模板中限制需要渲染的数据类型;"类型转换"是必不可免的。
回头去看QuickTemplate,它对此问题的解决方法,让我不禁莞尔:
<li>ID={%d row.ID %}, Message={%s row.Message %}</li>
QuickTemplate要求使用者在编写模板的时候,就直接指定插入变量的类型,如果是int,那么就使用 <%d %>
的标签,如果是字符串,就使用<%s %>
。
这需要引入新的语法不说,我认为也是会对模板使用者造成一定的心智负担,那么,有没有办法解决呢?
同样的模板代码,在gorazor中是这么表示:
<li>ID=@row.ID, Message=@row.Message</li>
而生成出来的代码是:
_buffer.WriteString("<li>ID=")
_buffer.WriteString(gorazor.HTMLEscape(row.ID))
_buffer.WriteString(", Message=")
_buffer.WriteString(gorazor.HTMLEscape(row.Message))
_buffer.WriteString("</li>")
经过一番尝试,我发现可以使用go/types库,对生成出来的代码做类型分析,当通过编译器知道row.ID
以及row.Message
的具体类型后,我自然可以将调用函数自动替换成为具体类型的版本,也就是说,重新生成以下的代码:
_buffer.WriteString("<li>ID=")
_buffer.WriteString(gorazor.HTMLEscInt(row.ID))
_buffer.WriteString(", Message=")
_buffer.WriteString(gorazor.HTMLEscStr(row.Message))
_buffer.WriteString("</li>")
这么一来,gorazor模板,也就能够做到零内存分配了!
压测的结果非常让人鼓舞:
若按比QuickTemplate快80%的结果看,gorazor 2.0应该是目前世界最快的go模板引擎了。
我其实觉得这样的性能测试意义并不大;因为很容易为压测跑分做优化,实际使用中,模板的方便性应该会更加重要;我会特别希望在gorazor 3.0中,增加Language Server Protocol的支持,这样就可以在VS Code等编辑器中,对模板也实现完整的智能补全。
基于 laravel blade 模板引擎改写, 支持原始 blade 模板引擎的语法. composer require hyperf/view-engine 生成配置 php bin/hyperf.php vendor:publish hyperf/view-engine 默认配置如下 本组件推荐使用 SYNC 的渲染模式,可以有效减少进程间通信的损耗 return [ 'engi
问题内容: 可以说我有两个表,和。 我创建如下视图: 如果执行以下操作: 如果是index和index ,那么我们应该可以通过两个索引搜索来做到这一点。 但是,如果我可以在一个索引中对两个表建立索引,甚至对视图建立索引,那都会很好,如果源表(或)发生更改,该方法可以立即自动更新。 在Oracle中有没有办法做到这一点? 问题答案: 我不能与Oracle相提并论,但是我相信物化视图可以做到这一点。
一、视图 1.1 简介 Hive 中的视图和 RDBMS 中视图的概念一致,都是一组数据的逻辑表示,本质上就是一条 SELECT 语句的结果集。视图是纯粹的逻辑对象,没有关联的存储 (Hive 3.0.0 引入的物化视图除外),当查询引用视图时,Hive 可以将视图的定义与查询结合起来,例如将查询中的过滤器推送到视图中。 1.2 创建视图 CREATE VIEW [IF NOT EXISTS] [
phpGrace 视图调用的2种方式 : 1、符合命名规则的自动调用 规则:控制器_方法名.php 控制在运行末尾会自动在视图文件夹下寻找符合 “控制器_方法名.php”规则的视图文件,一旦发现会自己引入此视图。 2、在控制器内使用 $this->display() 函数 参数:视图名称 示例: <?php class indexController extends grace{ publ
我用shell在Hbase中创建了一个表,其中包含两个列族。我可以用Hbase客户端API写进去。我正在使用phoenix JDBC驱动程序从中查询数据。我了解到HBase和Phoenix表之间没有一对一的映射。因此,我为现有的表创建了一个视图,但是每当我运行代码时,我会得到
我必须制作一个mvc应用程序,但是卡住了是使用Razor还是Aspx引擎。我在aspx中制作了许多Web应用程序,所以razor对我来说是新的。我在Razor中没有找到任何像在aspx中一样的DESIGN View(设计和源代码)。 我必须制作一个.net应用程序,通过它我可以通过通过Usb连接到计算机的Android手机发送短信。是否有任何代码或API类似于发送短信,如诺基亚移动AT命令.
我需要使用javaFX2执行以下操作: 1-)加载图像并使用imageView显示。[好的] 2-)右键单击并选择“添加节点”选项,屏幕上将出现一个黑色圆圈,您可以将圆圈拖动到图像的任何位置。[好的] 3-)使用鼠标的滚轮放大或缩小图像视图,在图像上提供“缩放感觉”。[确定] 3.1-)但是,每次缩放图像时,我都希望我的圆圈遵循缩放比例,这意味着它们不能保持在屏幕的相同位置。[不知道] 我的问题是
英文原文:http://emberjs.com/guides/views/built-in-views/ Ember中定义了一套用于构建一些非常基础的控件的视图,比如文本输入框、勾选框和选择列表。 这些视图有: Ember.Checkbox 1 2 3 4 <label> {{view Ember.Checkbox checked=model.isDone}} {{model.title