JavaScript Barcode SDK: Native vs. WebAssembly

A JavaScript barcode SDK can be built in C/C++ for high performance. We can compile C/C++ code to a Node.js addon or WebAssembly. Which one is superior? Let’s try Dynamsoft Barcode Reader SDK to find the answer.

What You Should Know

Node.js C++ Addon vs. WebAssembly

Speed

Performance is vital for SDK. According to our common sense, C++ addon should be the winner. However, it is interesting to see the performance gap when running C++ addon and WebAssembly in Node.js app.

Build C++ addon for Node.js

Download Dynamsoft Barcode Reader 6.2. You can choose one edition of Windows, Linux, and macOS. Here I use the Linux edition.

Get the sample code.

Copy libDynamsoftBarcodeReaderx64.so to /usr/lib:

sudo cp <Your PATH>/libDynamsoftBarcodeReaderx64.so /usr/lib/libDynamsoftBarcodeReader.so

Install node-gyp:

npm install -g node-gyp

Configure the building environment:

node-gyp configure

Build the extension:

node-gyp build

Install WebAssembly barcode SDK

npm install dbrjs

Create a simple Node.js barcode reader

var dbr = require('./build/Release/dbr');
var Module = require('dbrjs');

function decodeFileStreamAsync(fileName) {
  let stats = fs.statSync(fileName);
  let fileSize = stats["size"];

  fs.open(fileName, 'r', function(status, fd) {
    if (status) {
      console.log(status.message);
      return;
    }

    var source = fs.readFileSync(fileName);
      var typedArray = new Uint8Array(source);
      
      Module.onRuntimeInitialized = function() {
          let dbr = new Module.BarcodeReaderWasm("t0068NQAAAKTSQDbEid8CTEeNluhTXi+h35G8R03xIHsyYNzZoa2GiU2a8y7s5Z1lfHsMW5dNyZmH6jQL51HUcoB5EhpDeDk=");
          console.time('wasm');
          let results = dbr.DecodeFileInMemory(typedArray, "");
          console.timeEnd('wasm');
          let json = JSON.parse(results);
          let barcodeResults = json['textResult'];
          let txts = [];
          for (let i = 0; i < barcodeResults.length; ++i) {
              console.log("Value : " + Buffer.from(barcodeResults[i].BarcodeText, 'base64').toString('ascii'));
            }
            console.log("Done............................................................\\n");
      };
      
    let buffer = new Buffer(fileSize);
    fs.read(fd, buffer, 0, fileSize, 0, function(err, bytesRead, data) {
      console.time('native');
      dbr.decodeFileStreamAsync(buffer, fileSize, barcodeTypes, function(err, msg) {
        console.timeEnd('native');
        let result = null;
        for (index in msg) {
          result = msg[index];
          // console.log("Format: " + result['format']);
          console.log("Value : " + result['value']);
        }
        console.log("Done............................................................\\n");
      }, "");
    });
  });
}

Run the app to check the results.

Node.js Native vs WebAssembly

It turns out Node.js C++ addon is much faster than WebAssembly.

Portability

Although C++ addon has excellent performance, you have to use different compilers to rebuild it on different platforms. In contrast with C++ addon, WebAssembly is portable. If you have a Linux subsystem installed in Windows, you can quickly test the Node.js barcode reader by switching Linux and Windows.

WebAssembly for Linux and Windows

Web app development

Node.js C++ addon can only work on server-side, whereas WebAssembly can work on both server-side and client-side. To create an HTML5 barcode reader for web browsers, you can either implement a RESTful web service with C++ addon or build it with WebAssembly SDK.

Example: How to Use Dynamsoft WebAssembly Barcode SDK

Node.js

Create index.js:

const fs = require('fs');
var source = fs.readFileSync('test.jpg');
var typedArray = new Uint8Array(source);
const Module = require('dbrjs');
Module.onRuntimeInitialized = function() {
    let dbr = new Module.BarcodeReaderWasm("t0068NQAAAKTSQDbEid8CTEeNluhTXi+h35G8R03xIHsyYNzZoa2GiU2a8y7s5Z1lfHsMW5dNyZmH6jQL51HUcoB5EhpDeDk=");
    console.time('wasm');
    let results = dbr.DecodeFileInMemory(typedArray, "");
    console.timeEnd('wasm');
    let json = JSON.parse(results);
    let barcodeResults = json['textResult'];
    let txts = [];
    for (let i = 0; i < barcodeResults.length; ++i) {
        txts.push(Buffer.from(barcodeResults[i].BarcodeText, 'base64').toString('ascii'));
      }
    console.log(txts.join(", "));
};

Run the app:

node index.js

Web

var reader;
c.onRuntimeInitialized = function () {
  document.getElementById('anim-loading').style.display = 'none';
  buttonFile.disabled = false;
  buttonVideo.disabled = false;
  reader = new c.BarcodeReaderWasm("t0068NQAAAKTSQDbEid8CTEeNluhTXi+h35G8R03xIHsyYNzZoa2GiU2a8y7s5Z1lfHsMW5dNyZmH6jQL51HUcoB5EhpDeDk=");
};
 
if (reader) {
    try {
        // results = reader.DecodeBuffer(idd.buffer, imageWidth, imageHeight, imageWidth * 4, 7, "");
        let results = reader.DecodeFileInMemory(arrayBuffer, "");
        let json = JSON.parse(results);
        let barcodeResults = json['textResult'];
        let txts = [];
        for (let i = 0; i < barcodeResults.length; ++i) {
          txts.push(b64DecodeUnicode(barcodeResults[i].BarcodeText));
        }
        barcode_result.textContent = txts.join(", ");
      } catch (e) {
        console.log(e);
      }
}

Dynamsoft WebAssembly Barcode SDK

Conclusion

If you pursue extreme performance for Node.js, choose C++ addon. If the performance gap is not a big deal for you, WebAssembly is no doubt the best choice.

License

Get the trial license.

Source Code

https://github.com/dynamsoft-dbr/webassembly