原文连接:Lars Knoll – Evolution of the QML engine, part 1后端
QML做为一项技术对于Qt的成功变得愈来愈重要。它容许建立流畅的动画界面,与现今的市场预期相符。有三个主要的特性使得它更适合建立用户界面。首先是声明式语法,使得它很是容易建立用户界面,而且开发者和UI设计者工做在相同的代码基础上。其次,这项技术使原生代码集成变得相对容易,它承担了更多的程序逻辑以及C++所负的重任。最后,选择JavaScript做为QML语言不可分割的一部分,这样使得建立原型更加容易,而且为更普遍的用户提供了新技术。浏览器
今天的引擎是至关棒的基石而且知足了大多数用户的需求。固然也有一些咱们须要在将来解决的短处和问题。这个系列的博客将归纳咱们的研究而且呈现咱们计划要实现的解决方案。目标是在未来获得一个更好、更灵活、更易维护的QML引擎。缓存
让我从当前引擎所面对的一些问题开始。闭包
多个对象模型函数
当前的QML引擎使用V8 JavaScript引擎来执行属性绑定。每一个QML项内部有几个不一样的表示。一个面向V8(使用公开的V8 API),一个面向QML引擎,还有一个做为QObject暴露给原生Qt。这里的问题是须要QML引擎来同步这些不一样的表示,致使了大量的中间代码和至关高的内存消耗来维持这些不一样的表示。性能
经过JS闭包(closures)完成绑定优化
使用V8每一个绑定须要一个JS函数闭包。这须要把这个表达式重写成闭包,而后让V8再次解析这个重写的表达式。在V8中评估绑定须要调用JS函数,它使用大量的额外开销来模拟执行绑定的上下文环境。所以在咱们开发小型的用于QML引擎中的表达式解析器(叫作V4)的时候,它能够计算简单的表达式,这个解释器比经过V8计算快不少倍。动画
数据类型转换ui
使用V8计算表达式很慢的一个缘由是从Qt到V8或者从V8到Qt数据类型转换带来的额外开销。读写一个Qt属性,例如建立一个QVariant,将被转换为V8::Value。若是这个QVariant是字符串,将会调用字符串数据的复制。为了减弱这些开销引进了各类缓存机制,可是随之而来的是内存使用以及代码复杂性的增长。spa
QML域规则
QML语法上是项目树。内部项能够隐式查看外部项的属性,造成了一个良好定义的做用域链。不幸的是这个做用域链和传统的JavaScript不一样,不能用现有的JavaScript引擎直接实现。直接实现的惟一方法是嵌入慢的不被同意(deprecated)的with()语句。目前的解决方案包含了一个暴力(intrusive)补丁在V8中,而且仍然须要经过名字来查找全部的QML属性。
QML类型信息的丢弃
QML做为一种语言拥有类型信息。可是JavaScript是彻底无类型的。致使了这样一个事实,全部的类型信息在QML编译时被丢弃。保留这些类型信息将使咱们更好的优化QML表达式。
iOS和WinRT支持
iOS不容许内存可执行和可写,而这正是现有JS引擎所需的。WinRT根本不容许使内存可执行。这样的状况下,若是不写一个完整的V8解释器后端,就不能在这些平台上使用V8。
和V8上游一块儿工做
如上所述,咱们当前被迫维护一个至关大而且暴力的补丁集在V8之上。根本没有机会把这些标补丁合并到上游,由于V8专一于浏览器应用。
这些不一样的问题致使了一个研究项目,大约一年前由Nokia的Roberto Raggi和Aaron Kennedy发起。他们考察了根据QML的需求裁剪JS引擎的的可能性。这个项目代号为v4vm,以后被转移到Digia,Simon、Erik和我重拾这个项目而且继续研究。它做为一个playground项目存在于qt-project.org,已经有好几个月了。
今天咱们把这个研究项目集成到了Qt Declarative的一个开发分支,从如今开始咱们将在这个分支继续工做。
新的引擎包含了一个彻底遵循ECMAScript 5.1的实现,它能够运行于全部Qt支持的平台。它包含了一个JIT,目前能够工做在Linux、Mac和iOS。 目前已经完成了到当前QML引擎的集成,是经过一个兼容的V8 API层实现的,咱们计划在将来几周移除它。这个引擎能够运行全部的Qt Quick演示程序(有一些小问题)。
值得注意的一件事是,这个引擎专一于QML使用。这意味着咱们指望QML的性能变得比今天的更好。从另外一方面讲,纯JS性能并不必定像V8那样好。
然而咱们当前的基准数据(benchmark numbers)和纯JS代码同样是很是有但愿的,V8基准大约慢于Qt 4.8和Qt Quick 1中JS引擎3倍。咱们看到了很大潜力,能够在未来优化。
新引擎的细节和咱们将来的计划将在接下来的几篇文章中介绍。您能够在qtdeclarative的wip/v4分支找到代码。随意尝试吧。