5

I have a performance question for Angular 1.x. Is there any performance benefits to use function expressions vs filters to get values based on keys? Let me explain with examples.

I currently have a complex angular application with a number of filters used to get values based of an objects key. I have a lot of key/ID references in my data so I use a filter to get field values based of the key.

E.g. {{ ID123 | getField:'object':'field'}}

The custom filter would then do a async call (to DB) to get the object name I specify based on the key (ID123) and return the field I specify (instead of just showing the key).

I'm currently in the process of doing some performance clean up and I've read a lot about avoiding filters since they are a hit on performance. One thing I'm doing is using one-time bindings {{::ID123 | getField:'object':'field'}} but in some scenarios I can't do that (since I need the value to update).

I was then looking at function expressions instead of custom filters, e.g. {{getField(ID123,'object','field')}}. But I'm not sure if it would get any performance benefts.

You can see my plunker example where I compare the two.

https://plnkr.co/edit/hlL2LSOGjq5HsImUyqyu?p=preview

Would there be any performance benefits? Also is there a way to test or benchmark the difference between the two?

Thanks

  • "is there a way to test of benchmark the difference between the two"... There are a lot of questions about how to do this, including [this one on Stack Overflow](http://stackoverflow.com/q/27396539/215552). Regarding what performance benefits there are? Since you're doing an async call on each call to the filter or function, I'm guessing the filter or function is not your bottleneck; it's the async call. You should look at restructuring your queries so that the information comes all at once. – Heretic Monkey Jun 27 '16 at 21:27
  • Make sure you understand how digest cycles work. Many digests can be done in each cycle. Making asynch calls each digest is not efficient at all – charlietfl Jun 27 '16 at 21:32
  • I do cache the async calls, so each digest cycle it checks the cache and only makes the async call if there is no cache. As for performance, I'm more worried about the number of digest calls the filters are causing. Some pages have 20-30 of these filters. So during a digest cycle they are all being called. Do the functions also get called on every digest cycle? – Anand Patel Jun 28 '16 at 01:20
  • So I added a count on the filter and function. Looks like function gets called nearly 10x more then the filter. https://plnkr.co/edit/IoxmBjGQEB81lwoSc0iz?p=preview – Anand Patel Jun 28 '16 at 01:30

1 Answers1

4

Short answer: filter is better provided it's idempotent (i.e. the same input always returns the same output) and the input is not an object.


Long answer:

If you use a function, it will be called in each digest cycle, because Angular has to check that the output is the same. That means it will be called several times before the displayed data 'settles'.

If you use a filter and the input is not an object, it will be executed only if the input has changed, since Angular assumes that filters are idempotent unless their $stateful property is set to true. Objects are an exception to this, because it's costly to check if deep properties of objects are changed, so Angular executes the filter in every digest cycle, making it the same as a function.

Be careful with creating custom filters that are not idempotent, Angular will assume they are and not update the displayed data properly. If you must create one, mark them as $stateful.


Sources

This question is related and pointed me in the right direction:
Custom filter vs filter function in controller performance comparison

And this is the Angular documentation for filters (sections "When filters are executed" and "Stateful filters"):
https://docs.angularjs.org/guide/filter

Community
  • 1
  • 1
QOI
  • 231
  • 3
  • 11