levi
levi

Reputation: 1147

Angular 5 - Promise vs Observable - performance context

I have an Angular 5 site that receives data from a REST API, something like 1-4 requests to the API each page, and what happens is that the requests sometimes take a long time(and sometimes not).

Now, all the requests are being performed in one function using Observable :

return this.http.post(url, {headers: this.header})
        .map(res => res.json())      
        .catch(this.handleError)

my question is - could it be that the slow process is happening because an Observable is being used? Would Promises will be better for the performance? Or is there no difference between an Observable and a Promise in performance context?

Upvotes: 6

Views: 6410

Answers (4)

RMorrisey
RMorrisey

Reputation: 7739

The golden rule of performance troubleshooting is this: always measure; never jump to conclusions.

Start by reproducing a scenario where the page is running slowly. Check on the Network tab in your browser's developer console. How long does each network request take? Are the requests running in parallel, or is there a stair-step formation, where each request is not initiated until the previous one completes? Is there a long pause between requests, or does each one start immediately when the previous one finishes? Does the page appear loaded immediately when the last request is finished?

If you're unable to reproduce the problem, consider using a monitoring tool, like sentry.io, to help gather data. Analyze the data and find out what's taking so long. Is there a particular example of a record in your app that triggers this condition?

You should also look at application logs on the server side. How long is the server taking to respond to each request?

If you need to find out in detail what your rxjs code is doing, consider using this tool: https://github.com/cartant/rxjs-spy

I found this very helpful for local development.

Note that rxjs-spy introduces a large performance overhead, and is NOT suitable for production use.

Upvotes: 0

Anton Marinenko
Anton Marinenko

Reputation: 2982

It's not actually fair example by the last comment. More right usage RxJS in this scheme would be in this modified example:

https://stackblitz.com/edit/typescript-uajatd

Working browser performance: https://typescript-uajatd.stackblitz.io

And we can see RxJS mostly wins the race :)

Upvotes: 1

Uniphonic
Uniphonic

Reputation: 865

According to my tests, a Promise is more performant than an Observable.

I think Yanis-git test is a good start, but only shows part of the picture. It only calculates the starting of the Promise or Observable, but doesn't count the time for its resolution.

Here is the code I modified to take into account the resolution of the async functions as well: https://stackblitz.com/edit/typescript-xhhseh?file=index.ts

import { of, Observable, zip } from 'rxjs';
console.clear();

function testPromise(){
  console.time('promise');
  const promiseAry = [];
  for(let i = 0; i < 10000; i++) {
    promiseAry[i] = new Promise((resolve) => {
      setTimeout(() => resolve({
        name: 'promise'
      }))
    }).then(user => {
      // do something. Prefer not console.log because is ressource consuming.
    });
  }
  Promise.all(promiseAry).then(() =>{
    console.timeEnd('promise');

    // test Observables after Promises have completed
    testObservable();
  })
}

function testObservable(){
  console.time('observable');
  const observeAry = [];
  for(let i = 0; i < 10000; i++) {
    observeAry[i] = Observable.create((o) => {
      setTimeout(() => {
        o.next({
          name: 'observable'
        });
      });
    });

    observeAry[i].subscribe(user => {
      // do something. Prefer not console.log because is ressource consuming.
    });
  }
  let source$ = zip(...observeAry);
  source$.subscribe(([weatherInfo, tweetInfo]) =>
    console.timeEnd('observable')
  );

}

testPromise();

When I run the test in Chrome (on Mac), by visiting this page directly and opening the console: https://typescript-xhhseh.stackblitz.io/ I get these results:

promise: 279.65185546875ms
observable: 552.891845703125ms

And a very similar result in Firefox:

promise: 232ms - timer ended 
observable: 319ms - timer ended

Running them repeatedly, I always come up with Observable taking more time than Promise, which makes sense especially because Promises are now native to JavaScript, whereas Observables are not, so they wouldn't seem to be as performant.

Special thanks to Yanis-git for coming up with the original test that I forked.

Upvotes: 5

Yanis-git
Yanis-git

Reputation: 7875

because you question intrigue me. i have create same testing which look like this :

console.time('observable');
for(let i = 0; i < 10000; i++) {
  let user$ = of({
    name: 'yanis-git'
  });

  user$.subscribe(user => {
    // do something. Prefer not console.log because is ressource consuming.
  });
}
console.timeEnd('observable');

console.time('promise');
for(let i = 0; i < 10000; i++) {
  new Promise((resolve) => {
    resolve({
      name: 'promise'
    });
  }).then(user => {
    // do something. Prefer not console.log because is ressource consuming.
  });
}
console.timeEnd('promise');

and result looks like this (can be different on your browser / setup but proportion should be the same :

observable: 34.060791015625ms
promise: 103.4609375ms

EDIT :

Another implementation with both async traitment inside :

console.time('observable');
for(let i = 0; i < 10000; i++) {
  let user$ = Observable.create((o) => {
    setTimeout(() => {
      o.next({
        name: 'observable'
      });
    });
  });

  user$.subscribe(user => {
    // do something. Prefer not console.log because is ressource consuming.
  });
}
console.timeEnd('observable');

console.time('promise');
for(let i = 0; i < 10000; i++) {
  new Promise((resolve) => {
    setTimeout(() => resolve({
      name: 'promise'
    }))
  }).then(user => {
    // do something. Prefer not console.log because is ressource consuming.
  });
}
console.timeEnd('promise');

Result are close but race are win by observable.

observable: 160.162353515625ms
promise: 213.40625ms

live sample

if you want to check on stackblitz, please use real browser console to see timer output

Upvotes: 5

Related Questions