Avoid inactive SceneEditor/ExternalLayoutEditor to drain CPU

This commit is contained in:
Florian Rival
2018-04-28 14:37:10 +01:00
parent d8409d5f1e
commit b5ce3a996d
8 changed files with 76 additions and 13 deletions

View File

@@ -24,12 +24,6 @@
<!-- Progressive Web App support -->
<meta name="theme-color" content="#4ab0e4">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- Stripe.com Checkout -->
<script src="https://checkout.stripe.com/checkout.js"></script>
<!-- DocSearch support -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
</head>
<body>
<!-- Root div used for React `App` component rendering-->
@@ -53,5 +47,9 @@
<!-- DocSearch support -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
<!-- Stripe.com Checkout -->
<script src="https://checkout.stripe.com/checkout.js"></script>
</body>
</html>

View File

@@ -16,6 +16,7 @@ import DropHandler from './DropHandler';
import BackgroundColor from './BackgroundColor';
import PIXI from 'pixi.js';
import FpsLimiter from './FpsLimiter';
import { startPIXITicker, stopPIXITicker } from '../Utils/PIXITicker';
export default class InstancesEditorContainer extends Component {
constructor() {
@@ -245,6 +246,7 @@ export default class InstancesEditorContainer extends Component {
this.selectionRectangle.delete();
this.instancesRenderer.delete();
if (this.nextFrame) cancelAnimationFrame(this.nextFrame);
stopPIXITicker();
}
componentWillReceiveProps(nextProps) {
@@ -511,11 +513,15 @@ export default class InstancesEditorContainer extends Component {
pauseSceneRendering = () => {
if (this.nextFrame) cancelAnimationFrame(this.nextFrame);
this._renderingPaused = true;
stopPIXITicker();
};
restartSceneRendering = () => {
this._renderingPaused = false;
this._renderScene();
startPIXITicker();
};
render() {

View File

@@ -19,7 +19,9 @@ export default class BaseEditor extends React.Component<*,*> {
shouldComponentUpdate(nextProps: *) {
// Prevent any update to the editor if the editor is not active,
// and so not visible to the user
// and so not visible to the user. For editors that do special work when isActive
// is set to false (for example to disable PIXI rendering), shouldComponentUpdate
// should be overriden with a proper implementation.
if (!nextProps.isActive) {
return false;
}

View File

@@ -20,6 +20,18 @@ export default class ExternalLayoutEditor extends BaseEditor {
layoutChooserOpen: false,
};
shouldComponentUpdate(nextProps) {
// This optimization is a bit more cautious than the one is BaseEditor, to still allow
// children, and in particular SceneEditor and InstancesEditor, to be notified when isActive
// goes from true to false (in which case PIXI rendering is halted). If isActive was false
// and remains false, it's safe to stop update here (PIXI rendering is already halted).
if (!this.props.isActive && !nextProps.isActive) {
return false;
}
return true;
}
updateToolbar() {
if (this.editor) this.editor.updateToolbar();
}

View File

@@ -8,6 +8,18 @@ import { type PreviewOptions } from '../../Export/PreviewLauncher.flow';
export default class SceneEditorContainer extends BaseEditor {
editor: ?typeof SceneEditor;
shouldComponentUpdate(nextProps) {
// This optimization is a bit more cautious than the one is BaseEditor, to still allow
// children, and in particular SceneEditor and InstancesEditor, to be notified when isActive
// goes from true to false (in which case PIXI rendering is halted). If isActive was false
// and remains false, it's safe to stop update here (PIXI rendering is already halted).
if (!this.props.isActive && !nextProps.isActive) {
return false;
}
return true;
}
updateToolbar() {
if (this.editor) this.editor.updateToolbar();
}

View File

@@ -29,12 +29,14 @@ export default props => {
height: loaderSize,
}}
>
<RefreshIndicator
size={loaderSize}
left={0}
top={0}
status={'loading'}
/>
{props.show /* Don't render RefreshIndicator to avoid it to use a timeout that would wake regularly the CPU */ && (
<RefreshIndicator
size={loaderSize}
left={0}
top={0}
status={'loading'}
/>
)}
</div>
</div>
);

View File

@@ -12,6 +12,11 @@ const isDev = Window.isDev();
let client = null;
export const installAnalyticsEvents = (authentification: Authentification) => {
if (isDev) {
console.info("Development build - Analytics disabled");
return;
}
const sessionCookie = Keen.utils.cookie('visitor-stats');
const sessionTimer = Keen.utils.timer();
sessionTimer.start();

View File

@@ -0,0 +1,26 @@
import PIXI from 'pixi.js';
// PIXI has a ticker that is used by PIXI InteractionManager, and which
// frequently check if interaction happened. We may want to disable it
// when it's useless to do these interaction checks to save CPU usage.
/**
* Stop the PIXI Ticker used to monitor interactions
*/
export const stopPIXITicker = () => {
const ticker = PIXI.ticker && PIXI.ticker.shared;
if (ticker) ticker.stop();
};
/**
* Start the PIXI Ticker used to monitor interactions
*/
export const startPIXITicker = () => {
// Timeout ensure that the ticker is started even if other components
// call stopPIXITicker during the same tick (for example, when switching
// between SceneEditor tabs).
setTimeout(() => {
const ticker = PIXI.ticker && PIXI.ticker.shared;
if (ticker) ticker.start();
}, 50);
};