出人意料的性能测试

栏目: 编程工具 · 发布时间: 5年前

内容简介:在开发公司一次需求(就是一个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. 方案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');
    })
  }
复制代码

理论分析

理论上的时间复杂度 方案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之后的时间是多少呢?

出人意料的性能测试

想了那么久的数据结构,结果发现主流的电脑都可以忽略这点优化了,心情复杂。。。有没有大神告知一下是测试方法有问题还是真的机子太高端了,在这种数据级的情况下优化是没多大必要的?

出人意料的性能测试

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

代码阅读方法与实践

代码阅读方法与实践

斯平内利斯 / 赵学良 / 清华大学出版社 / 2004-03-01 / 45.00元

代码阅读有自身的一套技能,重要的是能够确定什么时候使用哪项技术。本书中,作者使用600多个现实的例子,向读者展示如何区分好的(和坏的)代码,如何阅读,应该注意什么,以及如何使用这些知识改进自己的代码。养成阅读高品质代码的习惯,可以提高编写代码的能力。 阅读代码是程序员的基本技能,同时也是软件开发、维护、演进、审查和重用过程中不可或缺的组成部分。本书首次将阅读代码作为一项独立课题......一起来看看 《代码阅读方法与实践》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具