Throttle screenshots to reduce impact on performance.
Brian Vaughn committed
Apr 6, 2019 at 13:58 UTC
d766d3b2e554e2998fbc3b30c6585520c75d95f3
7 files changed
+70
-24
package.json
+2
-1
@@ -56,7 +56,6 @@
56
"cli-spinners": "^1.0.0",
57
"clipboard-js": "^0.3.6",
58
"css-loader": "^1.0.1",
59
- "html2canvas": "^1.0.0-alpha.12",
59
"error-stack-parser": "^2.0.2",
60
"es6-symbol": "3.0.2",
61
"escape-string-regexp": "^1.0.5",
@@ -81,10 +80,12 @@
80
"flow-bin": "^0.94.0",
81
"fs-extra": "^3.0.1",
82
"gh-pages": "^1.0.0",
83
+ "html2canvas": "^1.0.0-alpha.12",
84
"immutable": "3.7.6",
85
"jest": "22.1.4",
86
"lerna": "^2.8.0",
87
"lint-staged": "^7.0.5",
88
+ "lodash.throttle": "^4.1.1",
89
"log-update": "^2.0.0",
90
"lru-cache": "^4.1.3",
91
"memoize-one": "^3.1.1",
src/devtools/store.js
+15
-5
@@ -1,6 +1,8 @@
1
// @flow
2
3
import EventEmitter from 'events';
4
+import memoize from 'memoize-one';
5
+import throttle from 'lodash.throttle';
6
import {
7
TREE_OPERATION_ADD,
8
TREE_OPERATION_RECURSIVE_REMOVE_CHILDREN,
@@ -35,6 +37,8 @@ const debug = (methodName, ...args) => {
37
const LOCAL_STORAGE_CAPTURE_SCREENSHOTS_KEY =
38
'React::DevTools::captureScreenshots';
39
40
+const THROTTLE_CAPTURE_SCREENSHOT_DURATION = 500;
41
+
42
type Config = {|
43
isProfiling?: boolean,
44
supportsCaptureScreenshots?: boolean,
@@ -129,8 +133,8 @@ export default class Store extends EventEmitter {
133
if (supportsCaptureScreenshots) {
134
this._supportsCaptureScreenshots = true;
135
this._captureScreenshots =
132
- localStorage.getItem(LOCAL_STORAGE_CAPTURE_SCREENSHOTS_KEY) !==
133
- 'false';
136
+ localStorage.getItem(LOCAL_STORAGE_CAPTURE_SCREENSHOTS_KEY) ===
137
+ 'true';
138
}
139
if (supportsFileDownloads) {
140
this._supportsFileDownloads = true;
@@ -416,6 +420,13 @@ export default class Store extends EventEmitter {
420
this.emit('isProfiling');
421
}
422
423
+ _captureScreenshot = throttle(
424
+ memoize((commitIndex: number) => {
425
+ this._bridge.send('captureScreenshot', { commitIndex });
426
+ }),
427
+ THROTTLE_CAPTURE_SCREENSHOT_DURATION
428
+ );
429
+
430
_takeProfilingSnapshotRecursive = (id: number) => {
431
const element = this.getElementByID(id);
432
if (element !== null) {
@@ -454,10 +465,9 @@ export default class Store extends EventEmitter {
465
profilingOperations.push(operations);
466
}
467
457
- const commitIndex = profilingOperations.length - 1;
458
-
468
if (this._captureScreenshots) {
460
- this._bridge.send('captureScreenshot', { commitIndex });
469
+ const commitIndex = profilingOperations.length - 1;
470
+ this._captureScreenshot(commitIndex);
471
}
472
}
473
src/devtools/views/Profiler/SidebarCommitInfo.css
+10
@@ -79,3 +79,13 @@
79
border: 1px solid var(--color-border);
80
border-radius: 0.5rem;
81
}
82
+
83
+.NoScreenshot {
84
+ width: 100%;
85
+ height: 200px;
86
+ background-color: var(--color-button-background-focus);
87
+ border-radius: 0.25rem;
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+}
src/devtools/views/Profiler/SidebarCommitInfo.js
+18
-8
@@ -18,7 +18,11 @@ export default function SidebarCommitInfo(_: Props) {
18
selectTab,
19
} = useContext(ProfilerContext);
20
21
- const { profilingCache, profilingScreenshots } = useContext(StoreContext);
21
+ const {
22
+ captureScreenshots,
23
+ profilingCache,
24
+ profilingScreenshots,
25
+ } = useContext(StoreContext);
26
27
const screenshot =
28
selectedCommitIndex !== null
@@ -97,14 +101,20 @@ export default function SidebarCommitInfo(_: Props) {
101
))}
102
</ul>
103
</li>
100
- {screenshot != null && (
104
+ {captureScreenshots && (
105
<li>
102
- <img
103
- alt="Screenshot"
104
- className={styles.Screenshot}
105
- onClick={showScreenshotModal}
106
- src={screenshot}
107
- />
106
+ {screenshot != null ? (
107
+ <img
108
+ alt="Screenshot"
109
+ className={styles.Screenshot}
110
+ onClick={showScreenshotModal}
111
+ src={screenshot}
112
+ />
113
+ ) : (
114
+ <div className={styles.NoScreenshot}>
115
+ No screenshot available
116
+ </div>
117
+ )}
118
</li>
119
)}
120
{screenshot != null && isScreenshotModalVisible && (
src/devtools/views/Settings/Settings.css
+6
@@ -51,3 +51,9 @@
51
border-bottom-right-radius: 0.25rem;
52
border-right: 1px solid var(--color-border);
53
}
54
+
55
+.ScreenshotThrottling {
56
+ background-color: var(--color-hover-background);
57
+ padding: 0.25rem 0.5rem;
58
+ border-radius: 0.25rem;
59
+}
src/devtools/views/Settings/Settings.js
+14
-10
@@ -117,16 +117,20 @@ export default function Settings({ portalContainer }: Props) {
117
{store.supportsCaptureScreenshots && (
118
<div className={styles.Section}>
119
<div className={styles.Header}>Profiler</div>
120
- <div className={styles.OptionGroup}>
121
- <label className={styles.Option}>
122
- <input
123
- type="checkbox"
124
- checked={captureScreenshots}
125
- onChange={updateCaptureScreenshotsWhileProfiling}
126
- />{' '}
127
- Capture screenshots while profiling
128
- </label>
129
- </div>
120
+ <label>
121
+ <input
122
+ type="checkbox"
123
+ checked={captureScreenshots}
124
+ onChange={updateCaptureScreenshotsWhileProfiling}
125
+ />{' '}
126
+ Capture screenshots while profiling
127
+ {captureScreenshots && (
128
+ <p className={styles.ScreenshotThrottling}>
129
+ Screenshots will be throttled in order to reduce the negative
130
+ impact on performance.
131
+ </p>
132
+ )}
133
+ </label>
134
</div>
135
)}
136
</div>
yarn.lock
+5
@@ -7053,6 +7053,11 @@ lodash.templatesettings@^4.0.0:
7053
dependencies:
7054
lodash._reinterpolate "~3.0.0"
7055
7056
+lodash.throttle@^4.1.1:
7057
+ version "4.1.1"
7058
+ resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
7059
+ integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
7060
+
7061
lodash@3.10.1, lodash@^3.10.0:
7062
version "3.10.1"
7063
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"