Code前端首页关于Code前端联系我们

mpx框架作者:小程序框架运行时性能评测

terry 2年前 (2023-09-22) 阅读数 83 #移动小程序

随着小程序在商务生活中的巨大成功,小程序开发在国内前端领域受到越来越多的关注。为了方便广大开发者更好的开发Widget,各种小Widget也层出不穷,呈现出百花齐放的局面。但目前业界还没有一份全面、详细、客观、公正的小程序框架评测报告,为小程序开发者选择技术时提供参考。所以我打算推出一系列文章,对业界流行的小软件框架进行全面、客观、公正的评价。本文是该系列的第一篇文章——运行时性能。

本文中,我们将对以下框架进行运行时性能测试(排名不分先后):

  • wepy2(https://github.com/Tencent/wepy) @2.0.0-alpha.20
  • uniapp (https://github.com/dcloudio/u... @2.0.0-26120200226001
  • mpx(https://github.com/didi/mpx) @2.5.3eon( https:// github.com /didi/chame... @1.0.5
  • mpvue(https://github.com/Meituan-Di... @2.0.6
  • kbone(https://github.com/腾讯/kb ... @0.8.3
  • taro next(https://github.com/NervJS/taro) @3.0.0-alpha.5

其中kbone和taro next都使用vue作为业务框架进行测试,人工更新时间当

  • setData调用次数
  • setData发送数据大小
  • 框架性能测试demo全部存放在https://github.com/hiyuki/mp-....开发者欢迎验证并修复错误

    测试计划

    为了让测试结果真实有效,我根据常见的业务场景构建了两个测试场景,即动态测试场景和静态测试场景。

    动态测试场景

    动态测试中,基于静态节点较少的数据动态渲染视图。视图更新比较耗时,setData调用条件是本次测试场景中的主要测试点。

    动态测试demo模拟了实际业务中常见的长列表+多tab场景。该demo中有两种优惠券列表数据,一种是可用优惠券数据,另一种是不可用优惠券数据,同时视图中只会渲染并显示其中一种数据。您可以模拟对列表数据的各种操作,并在上部控制区域中查看显示变化(剪切选项卡)。

    mpx框架作者:小程序框架运行时性能大测评

    动态测试demo

    在动态测试中,我在初始化之前通过函数代理对外代理了app、页面和组件构造器,并在Page的onLoad中使用mixin以及Component Inject setData拦截逻辑创建的hook来监听setData对所有页面和组件的调用,统计小程序的视图刷新时间和setData调用状态。该测试方法可以实现对框架代码的零侵入,可以追踪小程序的整个setData行为,并进行独立的耗时计算,具有很强的通用性。代码具体实现可以看https://github.com/hiyuki/mp-...

    静态测试场景

    静态测试模拟公司内静态页面的场景,比如页面业务活动和文章。页面有大量静态节点,没有数据的动态渲染。最初准备所需的时间是此场景中测试的重点。

    静态测试演示使用我去年发表的一篇技术文章中的HTML代码来定制和构建一个包含大量静态节点和文本内容的小程序。

    mpx框架作者:小程序框架运行时性能大测评

    静态测试演示

    测试流程及数据

    以下所有测试耗时数据均按微信小程序中真机5次测试的平均值计算,单位为ms。 Ios测试环境为手机型号iPhone 11,系统版本13.3.1,微信版本7.0.12。 Android测试环境为手机型号小米9,系统版本Android10,微信版本7.0.12。

    为了让数据显示不要过于混乱和复杂,文章中的数据主要是Ios测试结果。 Android测试结果与Ios匹配。总耗时比Ios大约高3~4倍。所有原始测试数据均存储在https://github.com/hiyuki/mp-...

    由于transform-runtime引入的core-js会对框架运行时量和运行时间产生一定的影响,并不是所有框架都Transform -编译期间将打开运行时。为了调整测试环境,在关闭转换运行时时执行以下测试。

    框架运行时体积

    由于不是所有框架都可以使用webpack-bundle-analyzer得到准确的包写入减去各个项目框架占用的体积,这里体积作为框架的运行时体积。

    演示总大小 (KB)框架运行时大小 (KB)
    原生270
    wepy26639
    unimpxeone 136109
    mpvue10376
    kbone395368
    芋头接下来183156

    本篇的结论测试是:
    native > wepy2 > mpx > mpvue > uniapp > chameleon > taro next > kbone

    结论分析:我们将frame和mp2的运行时间控制得最好;

  • taro next 和 kbone 由于动态渲染的特点,会在 dist 中生成递归渲染模板/组件,因此占用的体积较大。
  • 页面渲染时间(动态测试)

    我们使用 来更新页面 操作以触发页面重新加载。对于大多数框架来说,从触发更新操作到页面执行onReady的页面渲染时间是比较耗时的,但是对于像kbone、taro next这样的动态渲染框架,在页面上执行onReady并不意味着视图真正被渲染了。为此,我们设置了一个特殊的规则,即在页面 onReady 被触发后的 1000 毫秒内,不会有任何异常。当操作过程中发生setData回调时,最后一次触发的setData回调将作为页面渲染完成时间来计算实际的页面渲染时间。测试结果如下:

    页面渲染时间
    native60.8
    wepy264
    uniapp4 mpx52.6
    变色龙56.4
    mpvue117.8
    kb一98.698.656.4mpvue117.8 时间此测试所花费的时间与真实渲染时间并不对应。由于小程序本身不提供性能API,因此无法通过js准确测试真实的渲染时间。不过,从得到的数据来看,这个数据还是有一定参考意义的。

    本次测试的结论是:
    mpx ≈ chameleon ≈ uniapp ≈ native ≈ wepy2 > taro next ≈ kbone ≈ mpvue 由于 mpv ue在页面上完全渲染,接下来kbone和taro通过使用动态渲染技术,页面渲染需要很长时间,而框架的其余部分没有太大区别。

    页面刷新耗时(无后台数据)

    这里后台数据的定义是数据中存在但当前页面渲染中没有用到的数据。在这个演示场景中,它是不可用优惠券的数据。目前会的。当不可用优惠券数量为0时,对可用优惠券列表执行各种操作并计算更新时间。

    更新时间是从数据操作事件触发到对应的setData回调完成之间计算的

    mpvue使用当前时间戳(new Date)作为超时基准,设置setData超时为50ms 。油门操作,这种方法存在严重问题。当Vue中单个渲染同步过程的执行时间超过50ms时,后续组件patch触发的setData就会突破这个限制边界,以每次50ms的频率执行高频setData。无效调用。在本次性能测试demo中,当优惠券数量超过500张时,界面完全卡住。为了整个测试过程顺利运行,我对问题进行了简单的修复,并使用setTimeout重写了节流部分,以确保vue单渲染过程同步完成后调用setData发送合并的数据。然后就是mpvue的全部表现。测试都是基于这个补丁版本,补丁存放在https://github.com/hiyuki/mp-...

    理论上,在优化的假设下,native的性能应该是所有框架中最好的上限,但是在日常业务开发中我们可能无法对每一个setData进行优化。以下性能测试中的所有嵌入数据都是通过修改数据并完整发送来实现的。

    对于第一个测试,我们使用添加可用优惠券(100)该操作将可用优惠券数量从0逐步增加到1000:n❓6。

    5 105.4
    wepy2118.4168.6 204. 288.6347.8389.2434.2496539
    uni.298.2 99.6104102.4mpx110.487.282.28380.6
    1002003004005006007008009001000
    90.689.296.4
    116.8变色龙125.23133 ... 56.4762.4❀9291。 0 ,61468.81689.61933.22150.4❓❓❓❓❿芋头下一个470604.6902.4
    1056.2139。63139。 1707.81867.2

    然后我们点击一一删除可用优惠券(全部) > 添加可用优惠券s (1000) > 更新可用优惠券优惠券(1)❝ > 更新可用优惠券(全部) > 删除可用优惠券(1)

    删除(全部)添加(1000) 更新( 1)更新(全部)删除(1)
    原生32.8♾295.62229 2.283
    wepy256.8726.449.2535530.8
    uniapp43.6584.4♾♾131.2 mpx489.6
    5261165.6a变色龙​​765.695。 6 237.8
    1002003004005006007008009001000
    mpvue103.6669.4404.414.8433.6 120.22356.424 19.42357
    芋头 接下来126.6❙ 30。 07.81788.62318.2

    I update(all ) 的逻辑是循环更新每个列表项,形式为 listData.forEach((item)=>{item.count++ }) 。原来chameleon框架中的执行接口会完全卡住。跟踪发现chameleon框架并没有对setData进行异步合并而是在数据发生变化时直接同步发送。这样的话,在数据量为1000的场景下这样更新,会高频触发setData 1000次,导致界面卡顿;因此,在chameleon框架的测试demo中,我将update(all)的逻辑调整为深度克隆,生成更新后的listData,然后将其整个值赋给this.listData,以保证测试能够正常继续。

    本次测试的结论是:
    native > mpx ≈ uniapp > chameleon > mpvue > wepy2 > taro next > kbone

    结论-app mp框架内的化,随着数据量的增加,新的两帧耗时并没有明显增加;

  • wepy2在数据发生变化时也会将Data设置为prop数据,导致该场景下存在大量无效的性能损失,导致性能不佳;
  • kbone和taro则采用动态渲染方案。每次添加新的更新时,都会发送大量描述dom结构的数据。同时,动态递归渲染的耗时性质远大于常规静态模板渲染。这使得这两个框架在所有更新场景中都比其他框架更耗时。
  • 页面刷新耗时(有后台数据)

    刷新页面后,我们使用添加不可用的优惠券(1000张)

    183156

    183156

    183156

    , , 计数创建后台数据

    back add(1000)
    native45.2
    wepy2174.6 8 9.4
    mpx142.6
    mpvue134
    Kbone0
    taro next0

    mpx 受到 vue 的启发,通过优化 setData 来实现。它使用编译时生成的渲染函数来跟踪模板数据依赖性。 SetData在后台数据发生变化时不会被调用,而kbone和taro next则使用dynamic。渲染技术模拟底层Web环境,完全在顶层运行Vue框架,达到同样的效果。

    然后我们在没有后台数据的情况下执行与上面相同的操作进行耗时统计,首先递增100:

    1002003004005006007008009001000
    native8869.87851
    71.235141124
    79 ,4 84.489.893.299.6108
    wepy2121173.43♾173.4❝345 .6 434.8535.6
    uniapp❀ 135.4 112.4110.6106.4109.635141124
    114.4116118。 8117.4
    mpx112.686.284.684.687 .291.291.292.4 echamel 178.4178.2186.4184.6192192。 217.6232.6236.8
    mpvue139151173.4。 258.8303.4340.4384.6429.455 9.8746.60980.6126.81450.61705.4♾❙1705.4。 2367.82617
    太郎 下一个482.6626.2755909.621568.6 1740.61883.8然后按照表格中的操作顺序一一点击统计
    删除(全部)添加(1000)更新(1)更新(全部)n 43.4 299.889.289wepy2 43.27❀2♾6uniapp57.8589.862.6160.6154.4
    mpx45.8449变色龙184.6
    184.6
    220.8mpx❀124。 696.2423.4419430.6
    kbone121.4 2331.22448.414803
    129.8
    3947.21813.82290.2

    的本次测试结论为:
    Native > mpx > uniapp > chameleon next > 2❙ py❙o > 结论分析: 具有模板数据跟踪能力 mpx、kbone、taro next 三个框架的时间消耗有后台数据场景没有显着增加;

  • wepy2 中 Diff 精度不足,耗时没有明显变化;
  • 其余帧每次更新时都会发生变化。对后台数据进行deep diff,一定程度上改善了时间消耗。
  • 页面更新耗时(大数据量场景)

    由于 mpvue 和 taro next 的渲染都是在页面上完成的,而且 kbone 的渲染方案会添加大量额外的自定义组件,所以这三个框架将be 当优惠券数量达到2000张时,崩溃白屏。我们排除这三个框架,对剩下的框架进行大数据量场景下耗时的页面刷新测试

    首先在没有后台数据的场景下使用最近可用优惠券(1000张)❝数量可用优惠券最多 5000 个:

    10002000300040005000
    native332.6350412.6498.2。 4
    wepy2970.21531.42015.2496539
    20♾380。 4.2
    uniapp655.2593.4655675。 6718.8
    mpx532.2496548.6564601.8eee805.4 839.6952.81291.8 添加不可用优惠券(5000张)增加金额后台数据增加到5000并再次测试可用优惠券。数量增加到5000所需时间: ❀❙back 117.4
    wepy2511.6
    uniapp 285
    mpx ne349.8348.4430.4497 594.8
    wepy22470.43263。 44075.8
    uniapp715666.8709.2755.6mpx 538.8.变色龙1509.21672.41951.8222 2 。

    本次测试的结论是:
    native > mpx > uniapp > chameleon > wepy2

    结论分析:

    • 在大数据场景下,框架之间的基础性能差异会变得更加明显。 mpx 和 uniapp 仍然保持着接近原始性能的良好性能,而 chameleon 和 wepy2 则出现了明显的性能下降

    部分更新需要

    当可用优惠券数量为 1000 时,我们点击任意可用优惠券即可触发模式测试本地更新性能

    toggleSelect(ms)
    native2
    wepy2 2.6
    uniapp❿❿uniapp❿❿2. mpx2.2
    变色龙2
    mpvue289.6
    kbone2440.8
    taro next1975

    对于:❈nnnn❝变色龙 ≈ wepy2 ≈ uniapp > mpvue > taro next > kbone

    结论分析:

    • 可以看出,所有使用原生用户自定义组件进行组件化实现的框架,本地更新都是比较耗时的。极低,足以证明widget原生自定义组件的卓越性和重要性;
    • mpvue使用页面刷新,本地刷新时间大幅增加;
    • kbone 和 taro 其次是由于递归动态渲染的性能。开销巨大,使得本地更新同样耗时。

    setData调用

    我们将proxySetData的计数和大小设置为true,启用计数、设置数据的行统计,并根据数据计数和统计调用 setData 的次数。以及发送的数据量。

    操作流程如下:

    1. 100张增量可用优惠券(0->500)
    2. 更改为不可用优惠券
    3. 100张增量可用优惠券(500->100) 0)
    4. 有更新优惠券(全部)
    5. 切换到可用优惠券

    操作完成后,我们使用 ❀ 和 getCounter getSize

    方法获取累计的 setData 调用次数和数据金额。数据量计算方式为JSON.stringify,然后按照utf-8编码方式计算量。统计结果为:

    countsize(KB)
    native14803
    wepy235141124
    mpvue162127
    ❿x❿ chameleon2515319
    kbone 2210572
    太郎接下来92321

    本篇的结论测试为:
    mpx > uniapp > native > chameleon > we py2 > taro next > mpvue > kbone

    结论分析:❀mp实现了数据的最优框架;

  • uniapp 由于缺乏模板跟踪功能而紧随其后;每次创建组件时都会执行
  • chameleon。不必要的setData产生了大量无效的setData调用,但数据发送本身经过了diff,在数据发送量方面表现良好;
  • wepy2 组件在数据更新时调用 setData 以发送更新后的 prop 数据。因此产生大量无效调用,diff精度不够,发送的数据量也很大;
  • taro next 由于上层完全基于Vue,所以数据发送次数控制在9次,但是由于需要发送大量判断描述信息,所以发送数据量较大;
  • mpvue 也会产生大量数据,因为它使用很长的数据路径来描述与数据对应的组件;
  • kbone 不能很好地处理对 setData 的调用。上层运行vue时,仍然发送了22次数据,而且发送的数据量巨大,在这个过程中达到了惊人的10MB。
  • 页面渲染时间(静态测试)

    这里的页面渲染时间与前面介绍的动态测试场景相同。测试结果如下:

    页面渲染时间
    native70.4
    wepy28686。 115.2
    uniapp69.6
    mpx66.6
    变色龙65
    kbone 144.2芋头1. 本次测试的结论是:
    chameleon ≈ mpx ≈ uniapp ≈ native > wepy2 > mpvue ≈ taro next > kbone

    结论分析:

    • 除 kbone 和 taro next 使用动态渲染消耗随着时间增加,使用页面模板的 mpvue 的渲染性能稍差,而在其他框架中的静态页面渲染性能与原来相差无几。 合结论

      根据以上测试数据,得出最终的性能排名小程序框架: mpx> UNIAPP> Chameleon> Wepy2> mpvue> taro next> kbone一些私货

      kbone和taro next虽然使用了动态渲染技术,性能并不尽如人意,但我仍然认为它很棒技术解决方案。虽然本文进行了端到端的性能测试和比较,但性能并不完全与框架有关。开发效率和高可用性仍然是框架的重点。开发效率被认为是所有框架设计的初衷,但高可用性却被很大程度上忽视了。忽略。从这个角度来说,kbone和taro next都是非常成功的。与以往的翻译思路不同,这种平滑底层渲染环境的方式可以让上层Web框架完全运行起来,带来框架可用性的巨大提升。 ,非常适合简单操作小程序的迁移和开发。

      我主导开发的 MPx 框架 https://github.com/didi/mpx 选择了另一种方式来解决可用性问题,那就是改进 widget 的原生语法功能,避免 web 翻译带来的问题框架。不确定性和不稳定性,也能让性能非常接近原生。强烈推荐复杂业务小部件的开发人员使用它。在跨终端输出方面,mpx目前可以全面支持业界所有widget平台和web平台的同构输出。滴滴出行小程序是滴滴内部最重要、最复杂的小程序,完全基于mpx开发并使用该框架。提供的跨端功能,为微信、支付宝入口提供同步业务迭代,大幅提升业务开发效率。

      作者:董洪平(hiyuki),滴滴出行小程序负责人,mpx框架及核心负责人作者

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门