在开发公司一次需求(就是一个3层或者4层嵌套的表单数据(都展现层输入框))的各类处理时,脑子灵光一闪,想到了一些提升性能的方案,可是苦于时间(实际上是本身拖延),一直没有实际测试性能是否真的有提升。直到这几天才真正的去测试了一下,结果得出的结论出乎个人意料。javascript
测试嘛,数据确定不能用公司的,可是要接近公司的真实数据量,二话很少上,直接上 Mock.js ,配置以下:java
{
"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方案:性能优化
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');
})
}
复制代码
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');
})
}
复制代码
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');
})
}
复制代码
handleChange4(e,key){
console.time('test4');
let dict = this.state.dict;
dict[key] = e.target.value;
this.setState({
dict
},() => {
console.timeEnd('test4');
})
}
复制代码
理论上的时间复杂度 方案一、2不用说了其实都是同样的,O(n^3) 方案3理论上是O(1) 方案4理论上是O(n),且须要额外的空间复杂度O(n) 综合性能上的话应该是 方案3 > 方案4 > 方案2 > 方案1数据结构
为了保证测试结果,每次都修改3个输入框的值,每次都是新增输入3个一样的字符,废话很少说,直接测dom
方案1工具
方案2:性能
方案3:测试
方案4:
纳尼?竟然都差很少?
接下来用不一样的浏览器测试,数据来源换成生成好的JSON(保住数据彻底相同),增大数据量都试过,在浏览器不卡死能渲染的状况下,这几种状况下的渲染时间竟然是不相上下。
后来在每种方案调用的状况下都调用了一下console.time,发现4种方案消耗时间基本一致。就是说,方案一、2的遍历速度在个人电脑上遍历速度都很是快,致使了优化的效果并不明显。也就是说,在公司作的性能优化方案其实对于常见的电脑来讲其实意义不大(测试的数据量已经大于公司的数据量了)。可是对于低端机器,又没有合适的工具能够进行测试。。。
有心人可能发现我一开始的渲染代码中没有上key(故意删的),由于当React做diff时,只要子元素有key属性,便会去原v-dom树中相应位置(当前横向比较的层级)寻找是否有同key元素,比较它们是否彻底相同,如果则复用该元素,免去没必要要的操做。可是对于咱们此种测试,上述操做反而是没必要要的,由于咱们数据是固定的,上key反而多作了一次遍历(上面说的都是我猜的缘由),那么上了key以后的时间是多少呢?
想了那么久的数据结构,结果发现主流的电脑均可以忽略这点优化了,心情复杂。。。有没有大神告知一下是测试方法有问题仍是真的机子过高端了,在这种数据级的状况下优化是没多大必要的?