loading...

How to make your Javascript code run faster

singuerinc profile image Nahuel Scotti ・3 min read

A long time ago, in 2011, I wrote my first DNI (Spanish ID) validation script. I did it with ActionScript.

Some years later, after the Flash era, I re-wrote it for Javascript.

Recently, I went into a heavily Functional Programming learning process and as a goal, I propose myself to create a new module applying what I learned.

The result (not following FP paradigm too much I would say) is:

Better DNI

GitHub logo singuerinc / better-dni

The fastest Spanish DNI (NIE / NIF) validation out there.

npm Codacy grade Build Coveralls github Known Vulnerabilities npm bundle size (minified)

Better DNI

The fastest Spanish DNI (NIE / NIF) validation out there.

Installation

// npm
npm i better-dni
// yarn
yarn add better-dni

Usage

isValid / isNIF / isNIE / ctrlChar

import { isValid, isNIF, isNIE, ctrlChar } from "better-dni";
// validates any type of DNI (NIE or NIF)
isValid("Z7662566Y"); //=> true
// checks if it is a valid NIF
isNIF("06672804K"); //=> true

// checks if it is a valid NIE
isNIE("X1302311M"); //=> true

// returns the control letter in upper case
ctrlChar("X1302311M"); //=> 'M'
ctrlChar("X1302311"); //=> 'M'

Generators

NIF

import { randomNIF, randomNIFWith } from "better-dni";
randomNIF(); //=> '31719111H'

// returns a valid random NIF given the control letter
randomNIFWith("C"); // => '95652190C'

//

Quickly I found out that there are many modules doing the same…

Replicate what others already did is a little boring, so I changed my goal to

“Create the faster module to validate a DNI”

In this process, I found many ways to improve the speed of the code, although sometimes it looks a bit uglier, some of them made the code twice faster.

Note that you would get better results with newer versions of Node. I think https://jsperf.com is quite good in speed since it runs isolated with just one or two lines of code, but when I tried in “normal” computers with the whole module the difference is quite big. I would say that you should test your code in different environments and see where you can optimize.

Here is what I discovered:

str.substr() vs str.slice()

'0123456789'.slice(-9); // => '123456789'
'0123456789'.substr(-9); // => '123456789'

Winner: slice / x21 faster! / test

toLowerCase() vs toUpperCase()

I have to admit that I have never thought before why would one method be faster than the other. I was looking into the V8 code and looks like https://github.com/v8/v8/blob/master/src/string-case.cc#L16 is the answer to that.

'A'.toLowerCase(); // => 'a'

'a'.toUpperCase(); // => 'A'

This is especially useful if you need to compare two strings.

Before comparing them, better to convert them to lower case.

Winner: toLowerCase / slightly faster / test

Random image related to speed. You need one in all posts. Photo by James Traf on Unsplash

indexOf() vs object prop

const y = 'xyz'.indexOf('y'); // => 1

const y = {x: 0, y: 1, z: 2}['y'] // => 1

Winner: indexOf / slightly faster / test

String concatenation vs Template literals

I don’t know why I imagined that template literals were more complex than a simple string concatenation.

const x = 'x';

'yyy' + x;

'yyy${x}'; // faster

Winner: Template literals / slightly faster / test

Convert to number

parseInt('1234', 10); // => 1234

+'1234'; // => 1234

Winner: +sign / x6.12 faster! / test

Math.floor() vs Bitwise shift

I took some inspiration from this blog post.

Math.floor(1.123456789); // => 1

1.123456789 << 0; // => 1

Winner: Bitwise shift / slightly faster in jsperf but Math.floor() performs better much better in my MacBook Pro. / test

Other tips that could help your code to run faster

Tip 1

Do easy validations first and return as quickly as possible. Take a look at these snippets:

if(someComplexValidation(value) && value.length !== 9) return;

vs

if(value.length !== 9 && someComplexValidation(value)) return;

It’s the same code right? Do the “easy” validation first so your code does not run and return if the first validation does not pass.

Tip 2

Avoid using costly methods like “toUpperCase()” and try to use smart alternatives:

const n = 'XYZ'.indexOf('y'.toUpperCase()); // => 2

vs

const n = 'XYZxyz'.indexOf('y') % 3; // => 2

Tip 3

If you know that you can achieve the same result with different methods, find the one that works better for each specific case:

const x1 = 'xyz'.substr(0, 1); // => 'x'

const x2 = 'xyz'[0]; // => 'x'

const x3 = 'xyz'.slice(0, 1); // => 'x'

I hope this would help you to optimize your code!

Do you want to contribute, make it faster? Open a pull request:

singuerinc/better-dni

Posted on by:

singuerinc profile

Nahuel Scotti

@singuerinc

I make apps in HTML5, Javascript, Node.js, Ruby on Rails among others technologies.

Discussion

pic
Editor guide
 

Very interesting, thank you for sharing !

 

thanks for sharing!