5.1.2 性能优化的时机
您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!
5.1.2 性能优化的时机
在React Perf的界面中可以在Inclusive wasted time这一项中看到浪费掉的时间,这一次浪费了0.05毫秒,在页面中0.05毫秒是一段不起眼的时间,用户完全感觉不到。
如果说要优化代码避免这样的时间浪费,读者可能觉得没有必要。而且,前辈们已经提醒过我们不要过早进行所谓性能优化,读者可能知道《计算机编程艺术》作者下面的一句名言。
“过早的优化是万恶之源。”——高德纳
表面上看,这句话是说除非性能出了问题,不然就不要去花时间去优化性能。
照这么说,为了一个0.05毫秒的时间浪费似乎不值得去优化,但是,目前一个TodoItem组件的结构很简单,当一个被浪费的组件很复杂时,这样浪费的时间就会更长,更重要的是,这只是一个组件的浪费时间,而这个组件的数量是可变的,假设TodoList包含1000个待办事项,那就有1000个子组件TodoItem组件,每一次用户只能反转一个TodoItem组件的完成状态,也就是说会有999个TodoItem的渲染实际上是浪费掉的,那就浪费掉大约50毫秒的时间,这已经是一个能够被用户感知到的延迟时间,如果TodoItem增加更丰富的功能,产生的DOM结构更复杂,浪费的时间会更多。
难道前辈们说的话是错误的吗?并不是,只是前辈们的话被断章取义了,这句话的全文其实是这样。
“我们应该忘记忽略很小的性能优化,可以说97%的情况下,过早的优化是万恶之源,而我们应该关心对性能影响最关键的那另外3%的代码。”
——高德纳
看到了全文,就会对这句话有个全新的认识。
高德纳并没有否认性能优化的必要,而是说不要将性能优化的精力浪费在对整体性能提高不大的代码上,而对于性能有关键影响的部分,优化并不嫌早。因为,对性能影响最关键的部分,往往涉及解决方案核心,决定整体的架构,将来要改变的时候牵扯更大。
对于合并多个字符串,是直接使用+操作符合并?还是将所有字符串放在一个数组之后用join方法合并?不同JavaScript引擎和不同数量的字符串数量下,性能结果可能不一样,但是使用什么方法不大可能对整个应用造成关键的性能影响,这就是高德纳说的97%的情况;而选择用什么样的方式定义组件的接口,如何定义state到prop的转变,使用什么样的算法来比对Virtual DOM,这些决定对性能和架构的影响是巨大,就是那关键的3%。
所谓的“过早的优化”,指的是没有任何量化证据情况下开发者对性能优化的猜测,没有可测量的性能指标,就完全不知道当前的性能瓶颈在何处,完成优化之后也无法知道性能优化是否到了预期的结果。虽然我们也不知道高德纳在这句话里如何量化97%和3%这两个数字,但是在自己的工作中一定要有量化的性能指标,在上面的例子中,React Perf已经对wasted time这个指标给出了精确到毫秒小数点后两位的量化结果。
总之,虽然现在我们发现的浪费时间只有0.05毫秒,但这并不能成为我们无视这个性能问题的理由。
对于实例数量是动态的组件,一点点的浪费时间会因为实例数量增多而累积成很长的时间。开发者应该能认识到实际产品中会出现比开发过程中复杂得多的使用情况,还是以Todo应用为例,开发者每一次测试可能只有几个TodoItem,但是实际用户可能会创建成百上千的TodoItem,开发者永远要考虑到极端情况。
接下来,我们就来进一步改进这个Todo应用,其中会引入React组件的构建模式,记住这些模式,自然就会避免渲染的浪费时间。这也许会被认为是“过早的优化”,但是已经成为模式的优化方式,有利于代码的可读性。高德纳认为过早的优化是万恶之源,是因为这些优化往往让代码过于复杂而且难以维护,但是如果早期的优化能够让代码结构更加合理更加容易维护,何乐而不为呢? 深入浅出React和Redux