0

Background:

  1. I am writing a meteor app which initially populates a db with data retrieved via SOAP requests made to a API end point on a server somewhere.
  2. The initial request is a search via a search term I select. I get back a list of id's to records that match my search.
  3. Then I make another API request, but this time, for each of those records which I then store to my own db (only selected values, not all the data)
  4. If I have a list of search terms then the above is performed for each of these.
  5. To avoid 'callback hell' and because I though it was a good opportunity to learn something new I opted to use Promises ordered sequentially: which goes something like this: forEach searchTerm -> getTheResults.then.forEachResult->fetchRecord
  6. For short sequences of a 100 or so it worked fine but when it got up to 1000 it would hang. After speaking to uncle Google, I came across some threads about native Promises not being optimized in some way and the third party libraries that were faster. So I decided to try Bluebird, but before doing this I would test the assertion that it might make things faster.

Code The code below creates a sequence of 'sleep promises'. The idea was to swap out the Bluebird promise implementation and observe the time test takes to run over a sequence 5000 Promises long.

var Promise = require("bluebird"); // comment out for native implementation

function sleep(time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function() {
            // process.stdout.write(".");
            resolve(true);
        }, time);
    });
}
// the function is badly named, please ignore
function nativePromiseSequence(n) {
    // dont know how this first line works
    const arr = Array.apply(null, Array(n)).map(function () {});
    return arr.reduce(function(sequence, e, i, a) {
        return sequence.then(function() {
            return sleep(1);
        });
    }, Promise.resolve());
}

The Test I am using 'chai-as-promised' for testing the promises.

it('Run 5000 promises in a chain', function() {
            this.timeout(7000);
            return nativePromiseSequence(5000).should.eventually.equal(true);
        });

The Result Over a Promise chain of 5000 the test with Bluebird implementation completed about a second slower that Native promises

Have I made a mistake here or missed something?

timebandit
  • 794
  • 2
  • 11
  • 26
  • I just tested your code with a chain of 10000 - over 10 runs, averaged 15677ms for native and 15497ms for bluebird (didn't use `chai-as-promised` - just raw timings of your code using console.time/timeEnd) - to be honest, I don't think having a setTimeout in code that you are benchmarking is going to end up with very reliable results as setTimeout is not very accurate anyway, less accurate with smaller numbers – Jaromanda X Sep 12 '16 at 23:13
  • interestingly (maybe not very interesting), if you make the "sleep" extremely pointless, `var sleep = (time) => new Promise(resolve => resolve());` - bluebird is just under 3 times faster than native (36ms for 10000 vs 102ms) – Jaromanda X Sep 12 '16 at 23:20
  • and at 1000000 iterations (of the simple "sleep" with no timeout), bluebird completes in 1800ms, vs native at 12300ms - almost 7 times faster ... which shows you can make a benchmark to prove anything you want :p – Jaromanda X Sep 12 '16 at 23:26
  • I agree with Jaromanda that timing something that has a bunch of `setTimeout()` calls in it is pretty pointless. You're mostly just timing the relatively inaccurate `setTimeout()` calls. – jfriend00 Sep 13 '16 at 02:43
  • @JaromandaX thanks for console.time, learnt something new :). Very fair point, timeOut can be stripped away, but timing variances will exist for all competing processes on an OS, hence repeated testing is needed to see the general trend. So, in my case i did not see improvement. Perhaps the performance improvements are with the `Promisify` method. – timebandit Sep 13 '16 at 10:28
  • The browser build uses long stack traces by default. Run your own build should be even faster. – Benjamin Gruenbaum Sep 14 '16 at 11:17
  • @BenjaminGruenbaum I am running server side :) – timebandit Sep 15 '16 at 13:53
  • Are you running with `NODE_ENV = 'production'`? – Benjamin Gruenbaum Sep 15 '16 at 13:54

0 Answers0