Performance for filtering very long list


#1

I’m working on a view that uses server-sent events to receive log lines from another application and display them in a filterable list. Essentially, the view starts with an empty array as the model, and when the event source receives new log lines, it pushObjects them into the model. The view iterates over the model and puts each log line in an <li> element.

Below the list of log lines, there’s an input box that allows the user to filter the logs either by String#indexOf or via a regular expression. Currently, whenever the value of this input value changes, the controller filters the model by the user input and re-renders the list of log lines.

On a busy app, this can quickly escalate to thousands of lines being filtered. I realize at a certain point, I’ll have to limit the number of lines that can be kept around in the browser to filter, but I’m curious what I can do to stretch that limit as far as possible.


#2

Some ideas:

  1. I would say to simplify the filtering and only use indexOf. It’s quicker than a regex, and on a list of your size, could result in a noticeable difference.

  2. Put a debouncer on the input so that it doesn’t filter after every keystroke. I keep mine at 300ms and it works quite well.

  3. Try the arrayComputed functionality. I haven’t used it before, but based on what I’ve read, it could help in this situation (assuming that the list changes and not the query).

  4. You might be able to get creative. Let’s say that the user types in be into the search field. If the user then types a d, don’t try to filter all of the items, just filter the ones that matched be, since if they didn’t match be, they won’t match bed. And the reverse, if a character is removed, you can maybe return the cached result that you had from before without recalculating.

I’ve never dealt with a list that big in Ember, but it’s on the horizon for me, so I’m interested to see what you come up with. :slight_smile:


#3

I think the main bottleneck is probably the rendering of the large list, not necessary the filtering. You should take a look at some large list optimization techniques such as

  • use group helper
  • make each table row as simple as possible, and preferably remove Ember view completely in each row. you can use handlebar helper.

Another thing you could try to consider infinite scrolling for your view.


#4

I have filtered 50,000 item lists on the client side with good performance. You can even use intelligent string matching - the filtering is really not a problem here. In this blog post I benchmark several smart substring algorithms on ~16,000 strings in around 100ms.

Your problems will be:

  1. Ember data is slow. If you want this to scale you will need to implement a custom solution with jquery ajax (or consider ember model which is way faster than ember data but still slower than raw ajax and POJOs)
  2. Rendering. This is trivial to make super fast with Ember Listview or Ember Table which render lazily. I have used ember table a lot and found it to perform excellently on datasets with over 50k rows.

#5

The model is actually just an array that I’m pushing log lines onto when they get streamed to the client via an EventSource, so should be no performance concerns there. I suppose I could buffer lines and only add them to the model n lines at a time, but that’d have to depend on the speed in which lines are streaming in. I could also buffer the lines outside the model and only append groups of them every second or so. That actually wouldn’t be too bad.

ListView might be a good solution, but I’m also concerned about the readability effect that using translate3d has on text :\

I’ll try and cook up a demo of this today and post it here.