Proxy 的性能,可能比 DefineProperty 更差

系统 浏览器
在常用的几种浏览器中,测试结果比较统一,Proxy 的性能都弱于 DefineProperty,在 Safari,Firefox 中,DefineProperty 的性能大幅度领先。

老有人跑来跟我说 Proxy 和 defineProperty 相比,是性能的巨大提升。我一听,这不对劲啊,跟我学的知识不太一样,我明明记得Proxy 性能比 defineProperty 更差。

所以我就写了几个简单的例子来验证一下。

这个例子的逻辑非常简单,我们在大数据量循环的过程中,分别用 Object.defineProperty 与 Proxy 劫持的数据,执行一次 getter 与 setter。然后利用 performance.now 记录执行时间。

先看 defineProperty 的案例。

首先定义一个简单对象。

// 在循环中,我们会执行计算操作
var target = {
  total: 0
}

然后另外定义一个普通变量用于存储劫持过程中访问和设置的值。

然后用 Object.defineProperty 劫持 target。

Object.defineProperty(target, 'count', {
  get: function () {
    return b;
  },
  set: function (value) {
    b = value;
  },
});

然后循环 1000000 次,并打印执行时间。

var total = 0;
var now = performance.now()
for (let index = 0; index < end; index++) {
  total += target.count;
  target.count = index;
}
console.log('defineProperty', performance.now() - now)

接下来看使用 Proxy 的案例。

也是首先定义一个普通对象。

var target = {
  count: 0
}

然后使用 Proxy 代理。

let proxy = new Proxy(target, {
  get: (target, prop, receiver) => {
    return Reflect.get(target, prop, receiver)
  },
  set(target, prop, value) {
    return Reflect.set(target, prop, value)
  }
});

然后循环访问 getter 和 setter。

var total = 0;
var now = performance.now()
for (let index = 0; index < end; index++) {
  total += proxy.count;
  proxy.count = index;
  proxy.count
}
console.log('Proxy', performance.now() - now)

完整代码如下:

<script>
var end = 1000000
var b = 0;
var target = {
  count: 0
}

Object.defineProperty(target, 'count', {
  get: function () {
    return b;
  },
  set: function (value) {
    b = value;
  },
});
var total = 0;
var now = performance.now()
for (let index = 0; index < end; index++) {
  total += target.count;
  target.count = index;
}
console.log('defineProperty', performance.now() - now)
</script>
<script>
var end = 1000000
var target = {
  count: 0
}

let proxy = new Proxy(target, {
  get: (target, prop, receiver) => {
    return Reflect.get(target, prop, receiver)
  },
  set(target, prop, value) {
    return Reflect.set(target, prop, value)
  }
});

var total = 0;
var now = performance.now()
for (let index = 0; index < end; index++) {
  total += proxy.count;
  proxy.count = index;
}
console.log('Proxy', performance.now() - now)
</script>

我的测试电脑如下,性能强悍,对应的浏览器都是最新版。因此这里我们都定义的是 1000000 万次的执行,以更加方便的放大差异。

理论上绝大多数客户的电脑性能都很差,特别是许多面向 B 端的客户,所以如果有条件的朋友可以用客户的环境来做一下测试看看客户电脑上的真实差异

在 chrome 中执行结果为:

我连续执行了 10 次,发现执行结果都相差不大,执行时间上,Proxy 用时更久。

然后我切换浏览器,在 safari 中执行同样的代码,执行结果如下:

结果没想到,在 safari 浏览器中,Proxy 的性能严重低于 defineProperty。

然后我又把代码发给群友,群友用 QQ 浏览器执行了一下。

万万没想到的是,firefox 的执行结果差异最大。

然后我又尝试让 Proxy 代理的对象增加层级,然后进行 set 操作。

注意,这里只是简单的增加对象复杂度,并不代表更深层级的属性也能被代理。

var target = {
  count: 0,
  b: {
    c: 0
  }
}
for (let index = 0; index < end; index++) {
  total += proxy.count;
  proxy.count = index;
  proxy.b.c = target.count
}

验证结果发现,当层级变深,执行消耗的时间越长。下图是 chrome 的执行结果。

结论

在常用的几种浏览器中,测试结果比较统一,Proxy 的性能都弱于 defineProperty,在 safari,firefox 中,defineProperty 的性能大幅度领先。

当 Proxy 的目标对象深层次 getter/setter 时,会增加更多的性能损耗。

针对 Proxy 的性能,chrome 优化做得最好。但依然小幅度弱于 defineProperty。

针对于 defineProperty 的性能,firefox 和 safari 做得比较好,大幅度领先其他浏览器。

责任编辑:姜华 来源: 这波能反杀
相关推荐

2022-02-09 22:54:09

分辨率片源4K

2022-03-29 11:48:40

Go泛型测试

2021-10-17 21:48:01

Windows 11Windows微软

2020-09-07 12:50:25

VIDAR光缆世界地图

2009-04-24 10:49:57

Oracle性能优化错误

2022-06-30 08:01:33

ProxyReflecthandler

2011-05-20 10:05:13

Oracle性能优化

2018-03-07 09:35:17

区块链

2020-03-12 08:23:53

5G速度4G

2020-12-31 23:33:55

网络安全安全威胁网络攻击

2009-06-30 16:08:19

性能问题代码写法

2022-06-08 09:20:58

Python基准测试编程语言

2016-02-26 16:25:07

Linux桌面装机量

2020-11-23 08:46:19

5G

2022-03-02 10:36:37

Linux性能优化

2013-06-08 14:57:50

2022-09-05 09:10:19

Web3网络攻击网络安全

2019-06-19 10:00:45

vue.jsimbajavascript

2019-07-08 09:18:46

安卓Google华为

2016-05-31 10:52:18

软件定义SAN分布式存储
点赞
收藏

51CTO技术栈公众号