手机版

使用imba.io框架获得比vue快50倍的性能基准

时间:2021-08-22 来源:互联网 编辑:宝哥软件园 浏览:

我是标题党吗?是的,但它不是。为了证明。

上图显示vue、react和imba在todo项目中有60个todoItem来执行不同的crud操作。可以看到,imba每秒可以运行5w次以上。如果你想尝试这个测试,你可以访问Todos Bench。测试使用了Benchmark.js

Imba简介

Imba是一种新的编程语言,可以编译成高性能的JavaScript。它可以直接用于Web编程(服务器和客户端)开发。

以下是语法:

//自定义标记标记App //property prop items //方法定义defaudditemif @ input . value items . push(title : @ input . value)@ input . value=' deft oggle item item : completed=!Item : completed//mount imba . mount(element,into) //如果没有第二个参数,imba . mount app . vboxitems=[]-form . bar : submit . prevent . additem[email protected]将被装载到文档中. body默认情况下,item中项目的Button ' add ' ul Li . done=item : completed 3360 tap。切换项(item) item :标题可以看出作者喜欢ruby和pug,更喜欢缩进风格(个人不太喜欢这种语法风格)。具体语法请参考imba文档。当然,因为可以编译成js,所以服务器也可以编译成js进行节点开发。

Imba框架极快的性能基础

任何性能优化都有其理论基础,那么imba快速性能的基础是什么呢?答案是记忆化的DOM。

理论基础

浏览器的DOM操作可以说是浏览器的终极功能。无论框架是基于虚拟DOM还是真实DOM,最终都离不开DOM对象的操作。

HTML DOM是浏览器定义的访问和操作HTML文档的标准方法。但是操作DOM的接口是JavaScript。但是浏览器通常分别实现js引擎和渲染引擎。也就是说,页面的实际呈现部分与解析js部分是分开的。

用《高性能的 JavaScript》的话说,如果把DOM和js当成孤岛。他们需要一座沟通的桥梁。因此,每次执行DOM操作,都会过桥一次。

先说虚拟DOM。虚拟DOM的性能提升在于将DOM的比较放在js层。然后,通过比较差异来完成实际的DOM渲染。也就是说,虚拟DOM没有“真实”的性能增益,桥梁还在。在js引擎需要过桥的一侧只找到了一个智能大叔,对过桥的人和货进行了优化和限制(虚拟DOM的高性能diff算法,状态的批量更新)。

那么记忆化DOM是做什么的呢?将DOM节点的控件直接放入内存。类似这种优化。

函数getEls(sel) {//设置缓存if(!getels . cache)getels . cache={ };//如果缓存中存在el,则直接返回if(getels . cache[sel]){ return getels . cache[sel];}//未通过DOM查询const r=document . queryselectorall(sel | | ' '),length=r.length//缓存并返回元素节点returngetels.cache [sel]=(长度==1)?r[0]: r;}我们可以测试一下。这里我写了一个getElsByDocument和simplePerTest。

//获取节点函数getelsbydocument(sel){ const r=document。querySelectorAll (sel | | ' '),length=r.length直接通过query selectorall;返回长度==1?r[0]: r;}//simple performance test函数simpletest (fn,El){ const fn name=fn . name console . time(fn name)//2000 operations for(let I=0,len=2000我透镜;

该缓存节点查询的速度比querySelectorAll快140多倍。img节点越多,性能越高。如果imba框架中的所有节点都在内存中呢?同时,我们还会得到一个js运行时优化(大量的GC缩减),因为虚拟DOM需要维护一个树,多个crud后会产生大量无用的对象,这会导致浏览器执行GC,而memoized DOM不会对多个crud执行GC。(可能是渲染引擎中的GC?但是我感觉渲染引擎中的GC影响力比JS小很多。挖个坑,研究完渲染引擎再讨论)

框架实践

例子如下:

标记组件def render selfh1.title“欢迎”p.desc“我是一个组件”上面的自定义组件将被编译成以下js

var Component=imba . define tag(' Component ',function(tag){ tag . prototype . render=function(){ var $=this。$;//返回DOM返回这个。setchildren ($。$=$.$ | | [createelement ('h1 ',$,0,this)。标志('标题')。settext ('welcome '),createelement ('p ',$,1,this)。标志(。};});仔细看这里的函数,你会发现当组件第一次调用呈现时,它会使用createElement创建两个子节点,设置它们的属性并缓存它们。在第二次或第10,000次调用时,将缓存子数组,并且不会发生任何调用。

//第一次通话时,$。$不存在,$。$将等于以下数组。//第二次调用时,$。$确实存在,并且不存在$的运行时消耗。$=$.$ | |数组。查看源代码,我们可以看到setChildren函数在真实的DOM上运行。获取上一个DOM节点,执行一系列操作,然后返回并缓存当前节点。

tag . prototype . setchildren=function(new $,typ){ var old=this。_ tree _if (new$===old(!(new$) || new$。taglen==undefined)) {返回这个;};if(!旧字体!=3){ this . removeall children();appendNested(这个,new $);} else if(typ==1){ var caret=null;for (var i=0,items=iter$(new$),len=items.length我透镜;i ) {脱字符号=和解(此,项[i],旧[i],脱字符号);};} else if (typ==2) {返回此;} else if(typ==3){ var ntyp=type of new $;if (ntyp!='object') {返回this . settext(new $);};if (new$ new$。_ DOM){ this . removeall children();this . appendchild(new $);} else if(new $ instance of Array){ if(new $)。_type==5岁。_type==5) {和解协议(this,new$,old,null);} else if(Array的旧实例){和解(this,new$,old,null);} else { this . removeall children();appendNested(这个,new $);};} else { return this . settext(new $);};} else if (typ==4) {和解索引数组(this,new$,old,null);} else if (typ==5) {和解运算(this,new$,old,null);} else if((Array的new$ instanceof Array的old instanceof和解(this,new $,old,null);} else { //如果是文本呢?this . removeall children();appendNested(这个,new $);};这个。_ tree _=new $;归还这个;};如果我们使用动态属性。代码如下

标记组件定义渲染自拍1。Title' Welcome' #拥有red class p . desc . red=(math . random 0.5)' imba '的几率为50%,可以获得以下代码。从详细的检查中可以看出,IMBA提取变量并将其放入synchronized函数中,在每次渲染中只会执行synchronized中的数据,因此它仍然会获得极高的渲染速度。

var Component=imba . define tag(' Component ',function(tag){ tag . prototype . render=function(){ var $=this。$;返回this.setChildren($。$=$.$ || [ _1('h1 ',$,0,this)。标志('标题')。setText('Welcome '),_1('p ',$,1,this)。旗帜(' desc ')。设置文本('轮盘')],2)。已同步(($[1])。flagIf('red ',math . random()(0.5),true));};});准确提取不变量,然后不需要虚拟DOM计算,缓存真实的DOM。我们可以看到,内存化DOM不同于虚拟DOM,内存化DOM有实际的性能优势。

imba框架的“假”性能测试

上面我们已经看到了imba框架的理论基础,那么它真的比vue快50倍吗?当然不是。这就是为什么它说我是标题党。

浏览器的运行机制

浏览器本身只能达到60 fps(一秒钟刷新60次)。当然,其实对于体验来说,60fps的体验差不多就够了,也就是在浏览器渲染中大概需要17ms渲染一次。事实上,无论DOM每秒操作5w次还是1000次,浏览器渲染引擎都只会记录当前的脏数据。然后在需要渲染时重新绘制和重新排列。

现实世界中的记忆限制

面对内存化dom的缓存优化和更少的GC带来的运行时改进,我们需要更多的内存来缓存每个DOM节点。这在初始化渲染时会消耗很多。同时,我们浏览器的执行速度和渲染速度足够快,虚拟DOM完全够用。

Imba框架和浏览器想象

谷歌io大会上的Chorme Portals技术

单页应用程序(SPA)提供了良好的页面交互,但代价是复杂性较高。多页应用程序(MPA)更容易构建,但最终页面之间会出现空白屏幕。

门户结合了两者的优点,主要用于改善网页的交互体验,目标是无缝导航。它类似于内嵌在网页中的iframe,但可以导航到页面内容。当用户从一个页面跳转到另一个页面时,尽管网址会相应地改变,但没有必要打开另一个窗口。此时,内容标记的Portals将成为原页面的首页,原页面将在之后保持主流程位置。现场演示这对于购物体验的极大便利,以及演示漫画等单页应用。

js引擎和渲染引擎之间的关联

在过去,浏览器js引擎和渲染引擎根本不相关。我们只能通过setTimeout或者setInterval来写动画,没有办法知道浏览器什么时候空闲。但是,随着时间的发展,我们可以使用requestAnimationFrame和requestIdleCallback。RequestAnimationFrame要求浏览器在下一次重绘之前调用指定的回调函数来更新动画。requestIdleCallback方法将在浏览器空闲期间执行要调用的队列函数。

那么内置的DOM操作是否可以用在js引擎中,是否可以降低桥的性能消耗或者完全打开桥。让我们拭目以待。

版权声明:使用imba.io框架获得比vue快50倍的性能基准是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。