Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there reasons why FTSearch would not be a suitable alternative to DBColumn in a Type-Ahead on an XPage, when trying to improve performance?

Tags:

xpages

I have a general requirement in my current project to make an existing XPage application faster. One thing we looked at was how to speed up some slower type-ahead fields, and one solution to this which seems to be fast, is implementing it using FTSearch rather than the DBColumn we originally had. I want to get advice on whether this would be an OK approach, or if there are any suggestions to do what we need in a different way.

Background: While there are a number of factors affecting the speed (like network latency, server OS, available server memory etc.), as we are using 8.5.3, we have optimized the application in general as far as we can, making use of the IBM Toolkit to find problem areas, and also using the features IBM added to help with this in 8.5.3 (e.g. Partial Execution, using the optimized JS and CSS option, etc.). Unfortunately we are stuck with the server running on a 32bit Windows OS with 3.5Gb Ram for another few months.

One of the slowest elements to respond are in certain type-aheads which reference a large number of documents. The worst one averages around 5 or 6 seconds before the suggested list appears for a type-ahead enabled field. It uses SSJS to call a java class to perform a dbcolumn call (using Ferry Kranenburg's XPages Snippet) to get a unique list from a view, then back in SSJS it loops though the array to check if each entry contains the search key value, and if found it adds a highlight (bold) html tag around the search text in the word, then returns the formatted list back to the browser. I added a print statement to output the elapsed time it takes to run the code, and on average today on our dev server it is around 3250 ms.

I tried a few things to see how we could make this process faster:

  1. Added a Java class to do all processing (so not using SSJS). This only saved an average of 100ms.

  2. Using a view-scoped Managed Bean, I loaded the unique Lookup list into memory when the page is loaded. This produces a really fast type-ahead response (16ms), but I suspect this is a very bad way to do this with a large data set - and could really impact the general server if multiple users were accessing the application. I tried to find information on what would be considered a large object, but couldn't find any guidance or recommendation on how much is too much to store in memory (I searched JSF and XPage sites). Does anyone have any suggestions on this?

  3. Still in a Java class - instead of performing a dblookup to get the 'list' of all values to search through, I have the code run a FT Search to get the doc collection, then loop each doc to extract the field value I want and add those to a 'SortedSet' (which automatically doesn't allow duplicates), then loop the sorted set to insert the bold tags around the search term, and return that to the browser. This takes on average 100ms - which is great and barely noticeable. Are there an drawbacks to this approach - or reasons I should not do it this way?

Thanks for any feedback or advice on this. Pam.

Update Aug, 14. 2013: I tried another approach (inspired by the IBM/Tony McGuckin Insights application on OpenNtf) as the Company Search type-ahead in that is using managed beans and is fast across a lot of data.

4 . Although the Insights application deals with data split across multiple databases, the principle for the type-ahead is similar. I couldn't use a view with getAllEntriesByKey though as I needed to search for a string within the text too, not just at the start of the entry. I tried creating a ViewEntryCollection based on a view FTSearch, but as we have a lot of duplicate names in the column, this didn't give the unique list I wanted. I then tried using a NotesViewNavigator on a categorized view, and looping through that. This produced the unique list I needed, but it turned out to be slower than any of the other methods above. (I did implement these ViewNavigator performance tips).

like image 616
PNelson Avatar asked Aug 12 '13 19:08

PNelson


2 Answers

From my standpoint, performance may be affected by any of many layers every Domino application (not only XPages) consists of. From top - browser (DOM, JS, CSS, HTML...), network (latencies, DNS, SSO...) to application layer (effective algorithms, caches), database/API (amount of data, indexes, reader names...) and OS/hardware (disks, memory...)

According to things you tested:

  1. That is interresting, but could be expected: SSJS is cached and may use lower level API to get data (NAPI).
  2. For your environment (32bit/3.5G RAM - I expect your statement about 3.5M is typo) I DO NOT recommend to cache big lists, especially if you apply it as a pattern to many fields/forms/applications. Cache in WeakHashMap could be more stable, though.
  3. Use of FT search is perfectly fine, unless you need data that update frequently. FT index need some time and resources to update.

My suggestion is: go for FT, if it solves your problem. Definitely, troubleshoot FT performance in some heavy performance test on your server first.

like image 152
Frantisek Kossuth Avatar answered Oct 15 '22 20:10

Frantisek Kossuth


(I cannot comment because of my low reputation)

I have recently been tackling with a similar problem. Here are some additional points to consider:

  • Are there many duplicate keywords in the view? Consider making a categorized view for @DbColumn.

  • FTSearching a view is often slower than a database, I believe. See Andre Guirard's article. Consider using db.FTSearch() and refining your FT query to include view's selection @Formula, if possible.

  • The FT index can be updated programmatically with db.updateFTIndex(). If keywords are added rarely, but need to be instantly available, you can perform index update in keyword document's QuerySave event (or similar). We used this approach when the keywords were stored in different (much smaller) database and the update was very fast.

  • The memory consumption can be checked this way:

    1. Install XPages Toolbox from OpenNTF.
    2. Open your application.
    3. Create a JVM memory dump (Session dumps - Generate Heap Dump).
    4. Install Eclipse Memory Analyzer Tool
    5. Install IBM Diagnostic Tool Framework into Memory Analyzer.
    6. Load your memory dump into MAT. You will see every Java object and their sizes.

In the end, I believe that there is no single general answer to your question. You need to test different approaches to find the fastest solution in your environment.

like image 30
Lauri Laanti Avatar answered Oct 15 '22 18:10

Lauri Laanti