Fix unmounting performance regression in V8 (#7232)
As reported in #7227, unmounting performance regressed with React 15. It seems that `delete` has become much slower since we started using numeric keys. Forcing dictionary keys to start with a dot fixes the issue.
Dan Abramov committed
Jul 9, 2016 at 01:32 UTC
64e7602b3b9af9a43fd2f3495d3b13a398bb94d9
2 files changed
+25
-13
src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js
+10
-6
@@ -483,6 +483,10 @@ for (var type in topLevelEventsToDispatchConfig) {
483
var ON_CLICK_KEY = keyOf({onClick: null});
484
var onClickListeners = {};
485
486
+function getDictionaryKey(inst) {
487
+ return '.' + inst._rootNodeID;
488
+}
489
+
490
var SimpleEventPlugin = {
491
492
eventTypes: eventTypes,
@@ -620,10 +624,10 @@ var SimpleEventPlugin = {
624
// fire. The workaround for this bug involves attaching an empty click
625
// listener on the target node.
626
if (registrationName === ON_CLICK_KEY) {
623
- var id = inst._rootNodeID;
627
+ var key = getDictionaryKey(inst);
628
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
625
- if (!onClickListeners[id]) {
626
- onClickListeners[id] = EventListener.listen(
629
+ if (!onClickListeners[key]) {
630
+ onClickListeners[key] = EventListener.listen(
631
node,
632
'click',
633
emptyFunction
@@ -634,9 +638,9 @@ var SimpleEventPlugin = {
638
639
willDeleteListener: function(inst, registrationName) {
640
if (registrationName === ON_CLICK_KEY) {
637
- var id = inst._rootNodeID;
638
- onClickListeners[id].remove();
639
- delete onClickListeners[id];
641
+ var key = getDictionaryKey(inst);
642
+ onClickListeners[key].remove();
643
+ delete onClickListeners[key];
644
}
645
},
646
src/renderers/shared/stack/event/EventPluginHub.js
+15
-7
@@ -53,6 +53,10 @@ var executeDispatchesAndReleaseTopLevel = function(e) {
53
return executeDispatchesAndRelease(e, false);
54
};
55
56
+var getDictionaryKey = function(inst) {
57
+ return '.' + inst._rootNodeID;
58
+};
59
+
60
/**
61
* This is a unified interface for event plugins to be installed and configured.
62
*
@@ -96,7 +100,7 @@ var EventPluginHub = {
100
},
101
102
/**
99
- * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.
103
+ * Stores `listener` at `listenerBank[registrationName][key]`. Is idempotent.
104
*
105
* @param {object} inst The instance, which is the source of events.
106
* @param {string} registrationName Name of listener (e.g. `onClick`).
@@ -109,9 +113,10 @@ var EventPluginHub = {
113
registrationName, typeof listener
114
);
115
116
+ var key = getDictionaryKey(inst);
117
var bankForRegistrationName =
118
listenerBank[registrationName] || (listenerBank[registrationName] = {});
114
- bankForRegistrationName[inst._rootNodeID] = listener;
119
+ bankForRegistrationName[key] = listener;
120
121
var PluginModule =
122
EventPluginRegistry.registrationNameModules[registrationName];
@@ -127,7 +132,8 @@ var EventPluginHub = {
132
*/
133
getListener: function(inst, registrationName) {
134
var bankForRegistrationName = listenerBank[registrationName];
130
- return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];
135
+ var key = getDictionaryKey(inst);
136
+ return bankForRegistrationName && bankForRegistrationName[key];
137
},
138
139
/**
@@ -146,7 +152,8 @@ var EventPluginHub = {
152
var bankForRegistrationName = listenerBank[registrationName];
153
// TODO: This should never be null -- when is it?
154
if (bankForRegistrationName) {
149
- delete bankForRegistrationName[inst._rootNodeID];
155
+ var key = getDictionaryKey(inst);
156
+ delete bankForRegistrationName[key];
157
}
158
},
159
@@ -156,12 +163,13 @@ var EventPluginHub = {
163
* @param {object} inst The instance, which is the source of events.
164
*/
165
deleteAllListeners: function(inst) {
166
+ var key = getDictionaryKey(inst);
167
for (var registrationName in listenerBank) {
168
if (!listenerBank.hasOwnProperty(registrationName)) {
169
continue;
170
}
163
-
164
- if (!listenerBank[registrationName][inst._rootNodeID]) {
171
+
172
+ if (!listenerBank[registrationName][key]) {
173
continue;
174
}
175
@@ -171,7 +179,7 @@ var EventPluginHub = {
179
PluginModule.willDeleteListener(inst, registrationName);
180
}
181
174
- delete listenerBank[registrationName][inst._rootNodeID];
182
+ delete listenerBank[registrationName][key];
183
}
184
},
185