Performance Question About Using jQuery and Web Services with Large Lists

I got a question today via Twitter and my blog that I thought I’d share:

Further to Twitter message, I need to lookup values in a large list (thousands of items). Now, list performance and architecture issues aside, my intention is to use some JQuery enabled textbox which makes web service calls to suggest matching results as the user types. That’s not complex and I’m quite happy doing that. As with every time I use JQuery, I always think "should I really be solving this problem this way?". Making multiple web service calls as a user types (even with a delay) still seems wrong. I’m just not sure there’s another way to resolve the problem. What do you think?

As you know, Eric Shupps and I traded thoughts (along with a large number of other people) on this a while back:

I think that Eric and I reached the point where we realized that we were basically both saying that jQuery doesn’t kill performance: people kill performance.

There are good ways and bad ways to come at the problem.  Let me break down my thoughts…

First of all, "large lists" are, to a large degree, SharePoint myths. The real performance hit comes when you attempt to work with or display all of the items. As with any development, no matter the platform, the language, or the requirements, you have to be smart about it.

Secondly, it’s all about the use cases.  A relatively slow page which is used a few times a day is a very different situation than a slow home page.  You always have to consider who will be doing what, how often, why, etc.

Thirdly, when you use client-side code, you’re asking the client machine to do at least some of the work for you.  It’s very important to know what your client machine profiles are likely to be. If it’s a corporate environment, you already know the machine profiles.  (Right? You’ve done an inventory and you’re keeping it up to date so that you know what you can and cannot do?) If it’s an Internet site, then do you want to support Opera 5.0 as fully as IE8? Do you want to be able to assume that client machines have more than 1Gb of RAM or can support Flash or Silverlight? etc.

Lastly, from all of my experience using jQuery with the SharePoint Web Services, I’ve found them to be extremely efficient.  Basically, if you are doing something that you would expect to be non-performant through the UI, you can expect to see similar non-performant behavior with the Web Services, though it seems to me in many cases that the Web Services can actually be more efficient.  If you think about it, this makes sense.  You’re working at a lower level than full page refreshes, which requires much more work on the server’s part.

So, I’m not trying to dodge the questions; I just wanted to give a little of my perspective going into the specific answers.

"Should I really be solving this problem this way?"

Assuming that it will meet the requirements, I say "absolutely".  If this approach is going to give your users a good experience, then do it.  There are several things you can to to mitigate potential issues.

Probably the biggest mitigation would be to cache the GetListItems results.  If you can assume (note that I’m being careful about my assumptions; I know no more that what is in the questions above) that the "large list" is unlikely to change in a material way while the user is working with this piece of functionality, then making a single Web Service call and caching the results for the life of the page (or some decent time period) will keep the Web Service calls to a minimum.

Waiting for the user to type a certain number of characters before starting to do the Web Service calls can also help.  Going out and grabbing all of the items which have a value that starts with "T" may not even really be helpful, where "Thr" might be. If you look at my $().SPServices.SPDisplayRelatedInfo, I allow you to set the number of characters for just this reason.

Oh yeah, that reminds me: also consider using my jQuery Library for SharePoint Web Services. ;+)

7 Comments

  1. Always enjoy your perspective on the jQuery options in SharePoint Marc!

    One great aspect of jQuery (and javascript in general) actions is the ability to make it asynchronous and push the processing in the background. This can definitely improve the usability and responsiveness for the user but…it can sometimes mask some bad practices/decisions being made by the “developer” e.g. constantly recalling a web service. As you mention just ask yourself “Should I really do what I’m doing the way I’m doing it?”.

    Reply
  2. Hi Nick/Marc,

    For the benefit of Nick, it was my original question to Marc.

    I’m still not convinced on the use of web services to solve this problem, but I’m not sure what the other option is. I mean… if you have 1,500 list item IDs in a SharePoint list that you need a user to be able to lookup, clearly a drop down list isn’t appropriate here. Then again, clearly these aren’t the problems that web services were designed to solve and to be honest, I think this is probably only a viable solution because it’s an intranet application with little usage.

    I think as Marc points out, there are some obvious things we can do to reduce the communication between the client and the web services stack in order to make it a little bit more ‘sane’ to use this approach:

    – Caching the results of the web service
    – Calling the web service asynchronously based on a timer (rather than every key press)
    – Only calling the web service after a minimum number of characters have been entered.

    There is also the validation aspect here to consider e.g. how do you ensure that the values that have been entered into a column are valid unless you validate them with an event receiver. When I consider the solution to this problem holistically, it strikes me as cumbersome and clunky and I question the overall approach. However, everybody I speak to on the issue can’t suggest anything other. I guess it has to be implemented this way, very carefully.

    Shaun O’Callaghan

    Reply
    • Shaun:

      I don’t think that you should consider 1500 items as “large”. I expect that once you get this set up, you’ll be very pleasantly surprised at how well it performs, even if you do no communication reduction at all. Check out Jan Tielens’ post on this also:
      SharePoint Search-as-You-Type with jQuery

      Writing a general use version of this is something that I have on my list. I’ve also gotten code from several other people that works in their situations, but I need to come up with a more universally useful version.

      BTW, the nice thing about the jQuery approach is that you don’t need *any* back end code at all if you don’t want it. To me, this is a huge benefit in many environments, though it doesn’t sound like an issue for you.

      M.

      Reply
  3. To carry this along further I would be interested to know if you have come across client-side options for caching Marc?

    Caching is something I always implement at the server side but if there is are client-side alternatives that would definitely allow a complete solution without any code deployment. My first thoughts on how to achieve this would be storing the data from the web service in the page (even just hiding the non-matching options in the drop-down with CSS/jQuery)…but it doesn’t *feel* quite right. Thoughts?

    Reply
    • Sure, you can just “cache” in your JavaScript/jQuery logic. When you call the Web Service, you have the results in a variable. You can just treat the contents of that variable as a cache. In this case, on the first or second keypress, you could grab all of the items which have values which start with that character/those characters. As long as the user doesn’t change those characters, your cache is “good”. I’m not thinking of anything fancy here. It’s a set of tradeoffs between the memory requirements on the client side and the number of Web Services calls. There isn’t going to be any one “right” answer, as with most things. The use cases and the characteristics of the data are going to dictate the right approach.

      Adding to this based on our ongoing Twitter conversation, cache:true on the ajax call is a sort of all or nothing approach. It doesn’t allow you any real nuances. It makes much more sense in the context of grabbing a page from the server than data. The goal is to both minimize the number of Web Service calls as well as not overburden the client. You could certainly just query for all of the list items on page load and then you wouldn’t need to do any more Web Services calls. But that would require the client to “hold” all of that data. On the other end of the spectrum, you do a Web Service call every time the user hits a key. This will be the maximum possible (unless you do something reall stupid) number of Web Service calls. The “right” answer is somewhere in the middle. I would start with the many Web Service calls approach and see where the issues are, if there are any, and tweak from there. Keep in mind, too, that managing the “caching” in your script means that you can avoid talking to the server at all when you don’t need to; with cache:true, you still have to check with the server to see if anything’s changed.

      M.

      Reply

Leave a Reply