10000 Faster event delegation in WebAgg/NbAgg backends · matplotlib/matplotlib@b05eef9 · GitHub
[go: up one dir, main page]

Skip to content

Commit b05eef9

Browse files
committed
Faster event delegation in WebAgg/NbAgg backends
The if/else block is slower than a dictionary lookup/method call
1 parent 94e94e3 commit b05eef9

File tree

1 file changed

+74
-65
lines changed

1 file changed

+74
-65
lines changed

lib/matplotlib/backends/backend_webagg_core.py

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -272,73 +272,82 @@ def get_renderer(self, cleared=None):
272272

273273
def handle_event(self, event):
274274
e_type = event['type']
275-
guiEvent = event.get('guiEvent', None)
275+
handler = getattr(self, 'handle_{0}'.format(e_type),
276+
self.handle_unknown_event)
277+
return handler(event)
278+
279+
def handle_unknown_event(self, event):
280+
warnings.warn('Unhandled message type {0}. {1}'.format(
281+
event['type'], event))
282+
283+
def handle_ack(self, event):
284+
# Network latency tends to decrease if traffic is flowing
285+
# in both directions. Therefore, the browser sends back
286+
# an "ack" message after each image frame is received.
287+
# This could also be used as a simple sanity check in the
288+
# future, but for now the performance increase is enough
289+
# to justify it, even if the server does nothing with it.
290+
pass
276291

277-
if e_type == 'ack':
278-
# Network latency tends to decrease if traffic is flowing
279-
# in both directions. Therefore, the browser sends back
280-
# an "ack" message after each image frame is received.
281-
# This could also be used as a simple sanity check in the
282-
# future, but for now the performance increase is enough
283-
# to justify it, even if the server does nothing with it.
284-
pass
285-
elif e_type == 'draw':
286-
self.draw()
287-
elif e_type in ('button_press', 'button_release', 'motion_notify',
288-
'figure_enter', 'figure_leave', 'scroll'):
289-
x = event['x']
290-
y = event['y']
291-
y = self.get_renderer().height - y
292-
293-
# Javascript button numbers and matplotlib button numbers are
294-
# off by 1
295-
button = event['button'] + 1
296-
297-
# The right mouse button pops up a context menu, which
298-
# doesn't work very well, so use the middle mouse button
299-
# instead. It doesn't seem that it's possible to disable
300-
# the context menu in recent versions of Chrome. If this
301-
# is resolved, please also adjust the docstring in MouseEvent.
302-
if button == 2:
303-
button = 3
304-
305-
if e_type == 'button_press':
306-
self.button_press_event(x, y, button, guiEvent=guiEvent)
307-
elif e_type == 'button_release':
308-
self.button_release_event(x, y, button, guiEvent=guiEvent)
309-
elif e_type == 'motion_notify':
310-
self.motion_notify_event(x, y, guiEvent=guiEvent)
311-
elif e_type == 'figure_enter':
312-
self.enter_notify_event(xy=(x, y), guiEvent=guiEvent)
313-
elif e_type == 'figure_leave':
314-
self.leave_notify_event()
315-
elif e_type == 'scroll':
316-
self.scroll_event(x, y, event['step'], guiEvent=guiEvent)
317-
elif e_type in ('key_press', 'key_release'):
318-
key = _handle_key(event['key'])
319-
if e_type == 'key_press':
320-
self.key_press_event(key, guiEvent=guiEvent)
321-
elif e_type == 'key_release':
322-
self.key_release_event(key, guiEvent=guiEvent)
323-
elif e_type == 'toolbar_button':
324-
# TODO: Be more suspicious of the input
325-
getattr(self.toolbar, event['name'])()
326-
elif e_type == 'refresh':
327-
figure_label = self.figure.get_label()
328-
if not figure_label:
329-
figure_label = "Figure {0}".format(self.manager.num)
330-
self.send_event('figure_label', label=figure_label)
331-
self._force_full = True
332-
self.draw_idle()
292+
def handle_draw(self, event):
293+
self.draw()
333294

334-
else:
335-
handler = getattr(self, 'handle_{0}'.format(e_type), None)
336-
if handler is None:
337-
import warnings
338-
warnings.warn('Unhandled message type {0}. {1}'.format(
339-
e_type, event))
340-
else:
341-
return handler(event)
295+
def _handle_mouse(self, event):
296+
x = event['x']
297+
y = event['y']
298+
y = self.get_renderer().height - y
299+
300+
# Javascript button numbers and matplotlib button numbers are
301+
# off by 1
302+
button = event['button'] + 1
303+
304+
# The right mouse button pops up a context menu, which
305+
# doesn't work very well, so use the middle mouse button
306+
# instead. It doesn't seem that it's possible to disable
307+
# the context menu in recent versions of Chrome. If this
308+
# is resolved, please also adjust the docstring in MouseEvent.
309+
if button == 2:
310+
button = 3
311+
312+
e_type = event['type']
313+
guiEvent = event.get('guiEvent', None)
314+
if e_type == 'button_press':
315+
self.button_press_event(x, y, button, guiEvent=guiEvent)
316+
elif e_type == 'button_release':
317+
self.button_release_event(x, y, button, guiEvent=guiEvent)
318+
elif e_type == 'motion_notify':
319+
self.motion_notify_event(x, y, guiEvent=guiEvent)
320+
elif e_type == 'figure_enter':
321+
self.enter_notify_event(xy=(x, y), guiEvent=guiEvent)
322+
elif e_type == 'figure_leave':
323+
self.leave_notify_event()
324+
elif e_type == 'scroll':
325+
self.scroll_event(x, y, event['step'], guiEvent=guiEvent)
326+
handle_button_press = handle_button_release = handle_motion_notify = \
327+
handle_figure_enter = handle_figure_leave = handle_scroll = \
328+
_handle_mouse
329+
330+
def _handle_key(self, event):
331+
key = _handle_key(event['key'])
332+
e_type = event['type']
333+
guiEvent = event.get('guiEvent', None)
334+
if e_type == 'key_press':
335+
self.key_press_event(key, guiEvent=guiEvent)
336+
elif e_type == 'key_release':
337+
self.key_release_event(key, guiEvent=guiEvent)
338+
handle_key_press = handle_key_release = _handle_key
339+
340+
def handle_toolbar_button(self, event):
341+
# TODO: Be more suspicious of the input
342+
getattr(self.toolbar, event['name'])()
343+
344+
def handle_refresh(self, event):
345+
figure_label = self.figure.get_label()
346+
if not figure_label:
347+
figure_label = "Figure {0}".format(self.manager.num)
348+
self.send_event('figure_label', label=figure_label)
349+
self._force_full = True
350+
self.draw_idle()
342351

343352
def handle_resize(self, event):
344353
x, y = event.get('width', 800), event.get('height', 800)

0 commit comments

Comments
 (0)
0