【发布时间】:2020-06-27 05:33:51
【问题描述】:
我有一个简单的脚本,它每千分之一秒更新一个数字。如果我用 vanilla(标准)JS 写出来并运行它,它会消耗大约 40% 的 CPU(在所有 4 个内核上)。如果我在 React 中实现一个类似的功能,它会消耗我大约 60% 的 CPU,并且在至少一个内核上持续达到 100% 的峰值。
这里是代码。
在原版 JS (https://codesandbox.io/s/headless-dew-12vli)
index.html
<body>
<h1>Vanilla JS</h1>
<div>
<div>Counter: <span class="counter">1</span></div>
<div>Counter: <span class="counter">2</span></div>
<div>Counter: <span class="counter">3</span></div>
<div>Counter: <span class="counter">4</span></div>
<div>Counter: <span class="counter">5</span></div>
<div>Counter: <span class="counter">6</span></div>
<div>Counter: <span class="counter">7</span></div>
<div>Counter: <span class="counter">8</span></div>
<div>Counter: <span class="counter">9</span></div>
<div>Counter: <span class="counter">10</span></div>
</div>
<script src="src/index.js"></script>
</body>
script.js
const list = document.getElementsByClassName("counter");
for (let item of list) {
setInterval(() => {
item.innerHTML = Number(item.innerHTML) + 0.001;
}, 1);
}
在 React 中 (https://codesandbox.io/s/upbeat-wood-puhdu)
App.js
import React from "react";
import Counter from "./Counter";
export default function App() {
return (
<div className="App">
<h1>React</h1>
<Counter start="1" />
<Counter start="2" />
<Counter start="3" />
<Counter start="4" />
<Counter start="5" />
<Counter start="6" />
<Counter start="7" />
<Counter start="8" />
<Counter start="9" />
<Counter start="10" />
</div>
);
}
Counter.js
import React from "react";
import { useEffect, useState } from "react";
export default function Counter(props) {
const [amt, setAmt] = useState(parseInt(props.start, 10));
useEffect(() => {
// setAmt(parseInt(props.start));
const interval = setInterval(() => {
setAmt(amt => amt + 0.001);
}, 1);
return () => clearInterval(interval);
}, []);
return (
<>
<div>
counter:{" "}
<span id={props.start} className="counter">
{amt}
</span>
</div>
</>
);
}
将其降低到 1/100 秒可以稍微控制一些事情,但 React 仍然比普通 JS 更占用 CPU...
两个问题:
- 如何让这个 react 组件像它的类似 JavaScript 脚本一样高效?
- 总的来说,我怎样才能使这个脚本更高效?
【问题讨论】:
-
@user120242 反应键仅在渲染元素列表时才真正有用,请参阅Lists & Keys。对于 OP,react 已经真正优化了。尽可能多地用于 DOM 差异和状态管理的整个框架。请参阅reconciliation 和Optimizing performance。您是否正在尝试解决更深层次的潜在性能问题,或者只是探索 React 性能?
-
我在我正在处理的一个与 CPU 峰值有关的项目中注意到了这一点。我希望弄清楚如何解决它,因此我是一个体贴的开发人员,为我的最终用户和他们的功耗提供服务。
-
能成为一个体贴的开发人员真是太好了,但这感觉是边缘化的过早优化。我的猜测是尖峰只是在做它的事情,即状态更新,因此它正在区分 virtualDOM 并向实际 DOM 提交(刷新)更新。如果您以每秒数百/数千次的速度更新状态,我会期待这一点。您正在定义 很多 匿名回调函数,因此它们可能会构建并由浏览器批量收集垃圾。
-
好吧,更具体地说,在项目中我得到了 60% 的 cpu 使用率,导致风扇在我的机器上旋转......我将问题提炼到这个例子中,看看它是否是屏幕更新还是基础计算...两者都有,我敢肯定,但上述差异并非微不足道。
-
注意:你总是可以编写 vanilla JS 来超越 React。根据定义。就像你总是可以编写 asm 来超越其他任何东西一样。您不太可能做到(除了人为的示例和特定领域,即使那样差异很可能可以忽略不计),并且代码质量和生产力很可能会受到影响(随着代码的复杂性增加)。
标签: javascript reactjs performance optimization