内容简介:在开发公司一次需求(就是一个3层或者4层嵌套的表单数据(都展示层输入框))的各种处理时,脑子灵光一闪,想到了一些提高性能的方案,但是苦于时间(其实是自己拖延),一直没有实际测试性能是否真的有提高。直到这几天才真正的去测试了一下,结果得出的结论出乎我的意料。测试嘛,数据肯定不能用公司的,但是要接近公司的真实数据量,二话不多上,直接上 Mock.js ,配置如下:上面配置只是简版的,实际开发中的数据还有很多其他信息,但是不影响我的测试。
在开发公司一次需求(就是一个3层或者4层嵌套的表单数据(都展示层输入框))的各种处理时,脑子灵光一闪,想到了一些提高性能的方案,但是苦于时间(其实是自己拖延),一直没有实际测试性能是否真的有提高。直到这几天才真正的去测试了一下,结果得出的结论出乎我的意料。
表单的数据结构
测试嘛,数据肯定不能用公司的,但是要接近公司的真实数据量,二话不多上,直接上 Mock.js ,配置如下:
{ "data|4": [{ "title": "@ctitle(5)", "content|25": [{ "title": "@ctitle(5)", "content|25": [{ "key": "@string(6)", "title": "@ctitle(5)", "value": "@word(3)" }] }] }] } 复制代码
上面配置只是简版的,实际开发中的数据还有很多其他信息,但是不影响我的测试。
测试代码
看到数据结构可能很多老哥都猜到我要测啥了,我们在每次修改输入值的时候都要遍历数据,我们测的就是每次修改导致遍历数组所需要的时间。首先展示的代码如下:
renderForm(data) { return <> { data.map((item, index) => { return <div className="yijimokuai"> <h1>{item.title}</h1> { item.content.map((_item, _index) => { return <div className="erjimokuai"> <h2>{_item.title}</h2> { _item.content.map((__item,__index) => { return <div > <span>{__item.title}:</span> {/* <input type="text" value={__item.value} onChange={(e) => this.handleChange1(e,__item.key)}/> */} {/* <input type="text" value={__item.value} onChange={(e) => this.handleChange2(e,__item.key)}/> */} {/* <input type="text" value={__item.value} onChange={(e) => this.handleChange3(e,[index,_index,__index])}/> */} <input type="text" value={this.state.dict[__item.key]} onChange={(e) => this.handleChange4(e,__item.key)}/> </div> }) } </div> }) } </div> }) } </> } 复制代码
有4种input,每种对应一个不同的Onchange方案:
- 方案1:没有优化
handleChange1(e,key){ console.time('test1'); let data = this.state.data; for (let i = 0,flen = data.length; i < flen ;i++) { for (let j = 0,slen = data[i].content.length; j< slen; j++) { for (let k = 0,klen = data[i].content[j].content.length; k< klen;k++) { if (data[i].content[j].content[k].key === key) { data[i].content[j].content[k].value = e.target.value } } } } this.setState({ data },()=>{ console.timeEnd('test1'); }) } 复制代码
- 方案2:最简单的,加个break
handleChange2(e,key){ console.time('test2'); let data = this.state.data; for (let i = 0,flen = data.length; i < flen ;i++) { for (let j = 0,slen = data[i].content.length; j< slen; j++) { for (let k = 0,klen = data[i].content[j].content.length; k< klen;k++) { if (data[i].content[j].content[k].key === key) { data[i].content[j].content[k].value = e.target.value break; } } } } this.setState({ data },()=>{ console.timeEnd('test2'); }) } 复制代码
- 方案3:直接传递数组下标
handleChange3(e,key) { console.time('test3'); let data = this.state.data; data[key[0]].content[key[1]].content[key[2]].value = e.target.value; this.setState({ data },() => { console.timeEnd('test3'); }) } 复制代码
- 方案4:把数组中的值拷贝一份出来做一个字典,每次改值都在字典中改
handleChange4(e,key){ console.time('test4'); let dict = this.state.dict; dict[key] = e.target.value; this.setState({ dict },() => { console.timeEnd('test4'); }) } 复制代码
理论分析
理论上的时间复杂度 方案1、2不用说了其实都是一样的,O(n^3) 方案3理论上是O(1) 方案4理论上是O(n),且需要额外的空间复杂度O(n) 综合性能上的话应该是 方案3 > 方案4 > 方案2 > 方案1
开测
为了保证测试结果,每次都修改3个输入框的值,每次都是新增输入3个同样的字符,废话不多说,直接测
方案1
方案2:
方案3:
方案4:
纳尼?居然都差不多?
接下来用不同的浏览器测试,数据来源换成生成好的JSON(保住数据完全相同),增大数据量都试过,在浏览器不卡死能渲染的情况下,这几种情况下的渲染时间居然是不相上下。
分析
后来在每种方案调用的情况下都调用了一下console.time,发现4种方案消耗时间基本一致。就是说,方案1、2的遍历速度在我的电脑上遍历速度都非常快,导致了优化的效果并不明显。也就是说,在公司做的性能优化方案其实对于常见的电脑来说其实意义不大(测试的数据量已经大于公司的数据量了)。但是对于低端机器,又没有合适的 工具 可以进行测试。。。
后话
有心人可能发现我一开始的渲染代码中没有上key(故意删的),因为当React作diff时,只要子元素有key属性,便会去原v-dom树中相应位置(当前横向比较的层级)寻找是否有同key元素,比较它们是否完全相同,若是则复用该元素,免去不必要的操作。但是对于我们此种测试,上述操作反而是不必要的,因为我们数据是固定的,上key反而多做了一次遍历(上面说的都是我猜的原因),那么上了key之后的时间是多少呢?
想了那么久的数据结构,结果发现主流的电脑都可以忽略这点优化了,心情复杂。。。有没有大神告知一下是测试方法有问题还是真的机子太高端了,在这种数据级的情况下优化是没多大必要的?
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 微服务测试之性能测试
- Go 单元测试和性能测试
- 性能测试vs压力测试vs负载测试
- SpringBoot | 第十三章:测试相关(单元测试、性能测试)
- Golang 性能测试 (2) 性能分析
- 随行付微服务测试之性能测试 原 荐
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。