Make sure inefficient or chatty plugins don't churn too much CPU

Summary:
While profiling the high CPU load of the Analytics plugin, I noticed that most of the time is spend in rendering React. This makes sense as the component sends data very frequently, although it is definitely less efficient than it could be.

As shown in the following profile picture, it is clear that all the cpu churns up due to the amounts of re-renderings caused (every new incoming messages causes the plugin to analyse and process all it's data).

With background plugins, we already made sure that non-active plugins don't eat up all the CPU in React components if they process data inefficiently. Before:

{F238020503}

This change debounces how often we give new state to plugins, so that multiple updates get collapsed if the load becomes to high. After (note that not every 'emit' causes in an expensive render anymore, but that the rendering is now in a separate stack, the only remaining renderer is the debouncer component). After:

{F238020481}

Render stack happens now after a bunch of emits:
{F238021694}

This drops ~130% cpu to 70% cpu in the case of the analytics plugin, see below

Reviewed By: passy

Differential Revision: D21690494

fbshipit-source-id: 299c49c95f20af01e6ee3110b0c39478b3135c43
This commit is contained in:
Michel Weststrate
2020-05-26 04:49:21 -07:00
committed by Facebook GitHub Bot
parent c9d2acab08
commit 0da766f27b

View File

@@ -44,6 +44,7 @@ import {Message} from './reducers/pluginMessageQueue';
import {Idler} from './utils/Idler'; import {Idler} from './utils/Idler';
import {processMessageQueue} from './utils/messageQueue'; import {processMessageQueue} from './utils/messageQueue';
import {ToggleButton, SmallText} from './ui'; import {ToggleButton, SmallText} from './ui';
import debounceRender from 'react-debounce-render';
const Container = styled(FlexColumn)({ const Container = styled(FlexColumn)({
width: 0, width: 0,
@@ -383,6 +384,12 @@ class PluginContainer extends PureComponent<Props, State> {
} }
} }
// Let's make sure we reive new props in bursts of 200 ms, rather than continously
const DebouncedPluginContainer = debounceRender(PluginContainer, 100, {
leading: true,
trailing: true,
});
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>( export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
({ ({
connections: { connections: {
@@ -455,4 +462,4 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
setStaticView, setStaticView,
starPlugin, starPlugin,
}, },
)(PluginContainer); )(DebouncedPluginContainer);