出人意料的性能測試

前言

在開發公司一次需求(就是一個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方案:性能優化

  1. 方案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');
    })
  }
複製代碼
  1. 方案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');
    })
  }
複製代碼
  1. 方案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');
    })
  }
複製代碼
  1. 方案4:把數組中的值拷貝一份出來作一個字典,每次改值都在字典中改
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以後的時間是多少呢?

想了那麼久的數據結構,結果發現主流的電腦均可以忽略這點優化了,心情複雜。。。有沒有大神告知一下是測試方法有問題仍是真的機子過高端了,在這種數據級的狀況下優化是沒多大必要的?

相關文章
相關標籤/搜索