Mouse event throttling architecture - javascript

I have a set of nested DOM elements with mouse event handlers (mouseover, mouseout). Side effects of the events update other views; these updates are potentially computationally expensive, and can create annoying visual flicker, so I would like to minimize them. My first thought was to build a throttling mechanism that delays the handling of a mouse-over event for some interval, giving the mouse a chance to exit the element in question. If no exit occurs within the specified interval, the event is fired; if an exit occurs, the event is canceled without being propagated.
My question is whether existing UI frameworks already support such mechanisms, and, if so, which ones do so? While I can certainly build this, it seems like a problem that others might have solved already.

You can use underscore js' throttle on your mouse event handlers. This was recently blogged about on the toggl blog: http://blog.toggl.com/2013/02/increasing-perceived-performance-with-_throttle/. There was some monkey patching of jQuery involved, though, so it's not the cleanest method.

Related

Throttling events - Perfomance implications of adding and removing event listeners

This isn't a problem I'm having - it's more just a general interest query.
I've just implemented throttling on scroll events on my web app. I've done it in the way all tutorials teach you i.e. inside your function, you block the rest of its execution using some timer controlled variable which makes you wait until the function can be run again.
My question is this: surely in this case, on every scroll event, the function is still being run, it's just that the function is quickly exited so it doesn't take much of a performance hit.
I'm surprised that the standard correct way to throttle events isn't something like:
Add an event listener that runs a function.
When event occurs, run the function, remove the event listener and then set up a timeout to re-add the event listener at a later time.
I presume people far cleverer than me have thought of this and there are good reasons why not to do this.
Is it because it's unnecessarily fiddly? Is it much more processor intensive to add and remove listeners than it is to run empty functions?
I'm just curious. Thanks.
Neither of those is a performance concern. Starting to run a function and then bailing out is very cheap, and so too is adding/removing event listeners. So if you have a situation that can be solved by adding and removing event listeners, and it's easier to under than the other options, feel free to do it.
I can think of a couple reasons why i wouldn't do it though
It's narrow. There are very few problems that can be solved by removing an event listener. Throttling, yes, but even a very similar feature -- debouncing -- can't be done by removing the event listener. (Debouncing means to wait until there's a period of inactivity. So if the function keeps getting called quickly, you'll keep delaying longer. If you remove the event listener, you lose the ability to know that you need to wait longer)
You have to know how to tear down and set up the event listener. For your case that may be fine, but a general-purpose throttle utility (Eg, lodash's throttle function) may have no idea how the function is going to be called. If you use the setTimeout approach instead, then it will work regardless of how it's being called.

Understanding React's Synthetic Event System

This has been on my mind for a few days now.
As per the docs, React has synthetic event system, which is a a cross-browser wrapper around the browser's native event. Going through the docs, is my understanding correct that the custom (synthetic) event system, isn't about efficiency but rather cross-browser compatibility.
In other words, React still appends the event to the element rather than the more efficient approach of event-delegation on the parent element?
I also noticed this in Firefox Inspector which raised the initial curiosity.
The reason for asking the question is that I am working on an app where a user maybe able to select a thousand elements & drag them around the screen, so eventually event delegation is going to come up.
Alright, you perhaps already figured everything on your own, but as I asked myself the same questions, I figured I'd leave this here in case someone else is curious about not only using React but also getting an idea about how it works.
So, I'm not entirely sure about your question (especially the "append the event to element" part) but:
React is all about the virtual DOM. As the name implies, it is therefore built on top of the "real" environment that is the DOM. Consequently, everything takes place in that abstracted layer, including event handling.
Events appear in their "natural" environment, so the DOM or native (depending on the flavor of react you are using)
Consequently, you first need to bring the events up to the virtual DOM, compute your changes there and dispatch them to the representation of components in the virtual DOM, then bring the relevant changes back down to be reflected in the DOM appropriately.
Carrying changes up to the virtual DOM is effectively done by top-level delegation. This means that React itself listens to all events at a document level. This also means that technically, all your events go through one capture + bubbling loop before even entering the React-specific code. I would not be able to say what that implies performance wise, because you do "lose" the time associated to that first DOM traversal, but on the other hand you will do all your changes in the virtual DOM, which is faster than doing them in the real DOM...
Finally, SyntheticEvent is indeed a wrapper, which aims at reducing cross-browser compatibility issues. It also introduces pooling, which makes the thing faster by reducing garbage collection time. Besides, as one native event can generate several SyntheticEvent, it technically lets you create new ones easily (like a syntheticTap event that could be emitted if you receive a native touchStart then a native touchEnd in succession).
I have written a post with more details here. It is far from perfect and their might be some imprecision, but it can perhaps give you some more info on the topic.

jQuery bind() unbind() and on() and off()

Im working on a small adminarea for a webpage.
Does it make sense to unbind events for increasing performance(client)? Or does it cost more performance to unbind events and binding it 30Seconds later again?
My questions:
Is the idea behind bind()-unbind() or on().off() just increasing clientbased performance or should i use it for other scenarios? This question comes because my javascript code is growing and growing (about 30%) because of unbinding events. And i think, that some things may not work, when user interacts not, as i want...
.
EDIT: The most times im binding/unbinding keypress events, because i need the arrow keys for diff. scenarios.
Unbinding only to bind again for performance reasons is probably bug-prone and makes things overly complicated in most cases.
Instead of binding event listeners on many specific DOM elements, you could take a more "birds eye" approach and bind just a few listeners near the top of the DOM tree, and then when the event is triggered check what was actually clicked.
That way you won't spend CPU on binding/unbinding lots of event listeners, but instead take a small CPU hit when an event is processed (which is usually not noticeable).
This is covered in detail here: event delegation vs direct binding when adding complex elements to a page
If you try to bind and unbind you are creating race conditions for the garbage collector to actually come in and clean up your code. It is best to bind once and not have to bind again.
If your client side is expected to run for long periods of time (weeks, months) then you should look into memory management and memory leaks as more of a concern for performance.
Binding-unbinding (if not done correctly) may produce memory leaks which are hard to find. If you are using webkit, take heap snapshots of your performance with unbinding versus binding once and then you can make the best decision.
Here's a link:
http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/
One solution to avoid having to worry about this, especially if you deal with constantly changing elements or large quantities, is to register your event with the body and then specify a selector argument.
Like this:
$("body").on("click", ".my-actual-element", function(aEvent) {
// Event handler code goes here.
});
See more here $.on().

Why not take JavaScript event delegation to the extreme?

By now most folks on this site are probably aware that:
$("#someTable TD.foo").click(function(){
$(e.target).doSomething();
});
is going to perform much worse than:
$("#someTable").click(function(){
if (!$(e.target).is("TD.foo")) return;
$(e.target).doSomething();
});
Now how much worse will of course depend on how many TDs your table has, but this general principle should apply as long as you have at least a few TDs. (NOTE: Of course the smart thing would be to use jQuery delegate instead of the above, but I was just trying to make an example with an obvious differentiation).
Anyhow, I explained this principle to a co-worker, and their response was "Well, for site-wide components (e.g. a date-picking INPUT) why stop there? Why not just bind one handler for each type of component to the BODY itself?" I didn't have a good answer.
Obviously using the delegation strategy means rethinking how you block events, so that's one downside. Also, you hypothetically could have a page where you have a "TD.foo" that shouldn't have an event hooked up to it. But, if you understand and are willing to work around the event bubbling change, and if you enforce a policy of "if you put .foo on a TD, it's ALWAYS going to get the event hooked up", neither of these seems like a big deal.
I feel like I must be missing something though, so my question is: is there any other downside to just delegating all events for all site-wide components to the BODY (as opposed to binding them directly to the HTML elements involved, or delegating them to a non-BODY parent element)?
What you're missing is there are different elements of the performance.
Your first example performs worse when setting up the click handler, but performs better when the actual event is triggered.
Your second example performs better when setting up the click handler, but performs significantly worse when the actual event is triggered.
If all events were put on a top level object (like the document), then you'd have an enormous list of selectors to check on every event in order to find which handler function it goes with. This very issue is why jQuery deprecated the .live() method because it looks for all events on the document object and when there were lots of .live() event handlers registered, performance of each event was bad because it had to compare every event to lots and lots of selectors to find the appropriate event handler for that event. For large scale work, it's much, much more efficient to bind the event as close to the actual object that triggered the event. If the object isn't dynamic, then bind the event right to the object that will trigger it. This might cost a tiny bit more CPU when you first bind the event, but the actual event triggering will be fast and will scale.
jQuery's .on() and .delegate() can be used for this, but it is recommended that you find to an ancestor object that is as close as possible to the triggering object. This prevents a buildup of lots of dynamic events on one top level object and prevents the performance degradation for event handling.
In your example above, it's perfectly reasonable to do:
$("#someTable").on('click', "td.foo", function(e) {
$(e.target).doSomething();
});
That would give you one compact representation of a click handler for all rows and it would continue to work even as you added/removed rows.
But, this would not make as much sense:
$(document).on('click', "#someTable td.foo", function(e) {
$(e.target).doSomething();
});
because this would be mixing the table events in with all other top level events in the page when there is no real need to do that. You are only asking for performance issues in the event handling without any benefit of handling the events there.
So, I think the short answer to your question is that handling all events in one top level place leads to performance issues when the event is triggered as the code has to sort out which handler should get the event when there are a lot of events being handled in the same place. Handling the events as close to the generating object as practical makes the event handling more efficient.
If you were doing it in plain JavaScript, the impact of random clicks anywhere on the page triggering events is almost zero. However in jQuery the consequence could be much greater due to the amount of raw JS commands that it has to run to produce the same effect.
Personally, I find that a little delegation is good, but too much of it will start causing more problems than it solves.
If you remove a node, the corresponding listeners are not removed automatically.
Some events just don't bubble
Different libraries may break the system by stopping event propagation (guess you mentioned that one)

Which events are the most intensive?

Which events are the most resource intensive to have attached? Is a mouseover "worst" than a click? Are there any events that are known to be really harsh on the browser? I have my sights on IE7 mainly, as we are seeing performance issues there. We use event delegation where we can.
Or, how can I profile events which are actually running to determine which have the greatest impact on performance at runtime?
I'm interested in the events themselves, please don't tell me I need to go look into what my functions are doing in those events. Problems may exist there, but that's not my question.
So, to start with, events that fire more often can be more troublesome. So a mouseover event, which fires "continuously" as the mouse moves over an element, could cause a performance impact more easily than a click event, which can only fire as fast as the user can click.
However, it's the code you put in your handler that will have the real performance impact.
If firing speed is an issue, check out the excellent jQuery throttle/debounce plugin: https://github.com/cowboy/jquery-throttle-debounce
I'd imagine a callback's intensity is proportional to how many times it's called.
Events like mouseover or deviceorientation are more demanding than a click or similar 'one time' event.
The more an event have to check (and then throw) the more it consumes i.e. order from the max to the min:
mousemove throws an event at any move
mouseover throws an event at each move if pointing on a relevant item
mouseenter have to watch where is the cursor to then trow something
mouse click only throws an event when you click…

Categories