Bitwise Operators and Runtime

Yonatan Kra
WalkMe Engineering
Published in
5 min readOct 21, 2018

This is part of the bitwise operators series. If you need a refresher on bitwise operators, please read the first article (go ahead… I’ll wait).

In The Bits and Pieces section of my former article (linked above), we learned that you can represent several booleans with one integer using binary representation. We can also use bitwise operators to easily query the state of one or several booleans — or to change the values in a single line of code.

Conventional wisdom tells you that this kind of optimization is rarely required. Despite this dearth of enthusiasm, there are times when it IS #wisetousebitwise, for example, in high volume systems like apps with loops that run many times and/or over lots of data (renderers, for instance).

I’ve prepared, for your edutainment, just such an example of a specific case in which you would want to use bitwise operators for performance’s sake.

The App

Ready? In this example, we have a JavaScript Student class. It can be injected with a custom CompletedCourses class, which holds and controls the students’ completed courses.

The app features two buttons with two distinct onclick functions: start and startBits. start uses the regular boolean CompletedCourses class while startBits uses the CompletedCoursesBits class that uses bitwise operators.

Here’s the code:

The app — Just run main.js :)

The two buttons have the same interface (only with different method names so we can differentiate them). Time to get Shakespearean and see how these methods “shake”out.

Bitwise-eo and Boolea-ette

We’re going to test the app as follows: First, we’ll set up 10,000 students. Next, we’ll set the completed courses for each student. Finally, we will query the completed courses for each student.

A simple jsPerf comparison table shows a difference in run time between the two classes in favor of the bitwise operations:

https://jsperf.com/bitwise-vs-boolean-data-handling/1

The boolean version is 44% slower in this case. Let’s see what’s happening behind the scenes (or should I say, backstage… get it?).

Runtime Breakdown

I’m going to replicate the jsPerf results on my computer to get a closer look. I’ll run the same example 1000 times for each case (boolean vs. bitwise). You can use this gist to replicate the results yourself and play with the example.

The startBits function time consumption after 1000 iterations.
The start function time consumption after 1000 iterations.

In the left-hand side of the above images, you can see the functions’ runtime breakdown for each line of code. It is clear that everything takes longer in the non-bit solution. Who’d have thunk it?!

The Init Method

The two constructors initiate the course list differently.

We can already see the first difference in the init function. In order to explicitly fill in “falses” in every category, we must create an array and fill it with “false.” With the bits class we only need to set the variable to “0.” With bitwise operations, it looks like this:

“00000000000000000000000000000000”

While you might be tempted to suggest that undefined should be considered as false to obviate the need to set up the falsy values, if you work with a typing system (e.g., TypeScript), this might result in errors.

Another con for the booleans is memory consumption — We save multiple booleans (four bytes each), and instead use one integer (only eight bytes total).

Can you fit just one more boolean into that car?

completeCourse

In order to define a course as complete, we just need to shift the boolean from false to true. Same goes for bits — using the Bitwise Zero Fill Left Shift and the Bitwise OR we learned in the first article. The result: According to the index of the course, we will set the number to “1” in the status.

Even though the operation looks that same (set false to true — or change one bit to “1”), there’s clearly a major difference. In our example, the bitwise operation was faster by around 35%!

getCompletedCourses

These two methods look almost the same. The difference is the filter’s callback. Are you ready for the performance results?

The bitwise operations took 1165 ms compared to the 1562 ms that the boolean check took for the same data.

Now — if that’s not holy cow dung, then I don’t know what is; these methods implement the same interface, return the same value, and still, the bits form left boolean in the dung… er, dust!

A Mid-Summary Night’s Dream

In this article we saw an example of just how much faster bitwise operations can be. Notice the nature of our example app: We compared boolean to bitwise with a 10,000 student data set, and repeated the test 1000 times. “Loop”y as a dingbat on bath salts! (AKA, an example of where bitwise operations may come in handy).

Take a look at Angular’s newest renderer (to date) — the Ivy engine. It uses bitwise operations — and you can count on it to be performant (well, not just because of that; but still, showing that Angular uses bitwise operators does add to my claim’s credibility).

So — next time you have an app that has lots of filters (loops with booleans), and it gets stuck in the loops — consider using bitwise operators instead of comparing booleans.

Many thanks to Gergo Ertli and Aaron Weiss for their invaluable proofreading and content-editing assistance.

--

--