在開發公司一次需求(就是一個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以後的時間是多少呢?
想了那麼久的數據結構,結果發現主流的電腦均可以忽略這點優化了,心情複雜。。。有沒有大神告知一下是測試方法有問題仍是真的機子過高端了,在這種數據級的狀況下優化是沒多大必要的?