Logo of AppSignal

Menu

jQuery toggle() is slow, JavaScript to the rescue

Roy Tomeij on

jQuery is a great library to get things done fast, reliable and cross browser. Sometimes however it’s too slow and you’re better off using plain ol’ JavaScript, like when trying to toggle visibility on 500 elements in the DOM.

The problem

In AppSignal we have the “event tree”: a list of actions associated with a request and their performance, broken down into sub actions. It looks like this:

Screenshot of AppSignal event tree

When there are a lot of similar events on the same level, we show only one plus a “show n similar events” link. There can be a lot of similar events; we found out about our slowness when we had to hide and show 547 of them. For this we initially used jQuery’s toggle(), which took about 5 seconds to toggle the visibility of these 547 list items we targeted by class name.

Pure JavaScript instead of jQuery

After fiddling around for a bit we tried a really simple JavaScript approach that still checks the current state and shows/hides an element accordingly. We switched to finding the elements we want to toggle with querySelectorAll('.foo') for better performance. It’s supported by all modern browsers and IE8+, which is fine for our app, bypassing jQuery’s cross browser compatibility code. We could have used getElementsByClassName('foo') instead, which has about the same performance but limits browser support to IE9.

While we noticed performance improved significantly by simply using this feature, nothing beats a jsPerf test. This one was created to test the performance of toggling the visibility of 500 list items using jQuery’s toggle() versus querySelectorAll() and getElementsByClassName(). Please note that the pure JavaScript implementations are based on CoffeeScript output. We ran the test twice on multiple devices and the outcome is pretty clear (operations per second, higher is better):

Screenshot of AppSignal event tree

Conclusion

Don’t try doing this with jQuery. It’s a great library, but there’s a price to pay for the overhead. Consider not using it if you don’t have to.

10 latest articles

Go back

Subscribe to

Ruby Magic

Magicians never share their secrets. But we do. Sign up for our Ruby Magic email series and receive deep insights about garbage collection, memory allocation, concurrency and much more.