Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speeding up jQuery AutoComplete (Unavoidably long lists)

I began my journey to speed up jQuery's autocomplete earlier this afternoon, and decided it was probably a good idea to begin memcaching everything. As suggested in this article: Speeding up autocomplete.

However, I am still dealing with slow response time even after installing and using Memcached.

The problem in my case is that I am dealing with extraordinarily long lists, in my case, over 6700 individual members. (All genera or genuses of all plants)

The bottleneck seems to be constructing the table and populating the client-side list, and it is not caused by retrieving the information from Memcached.

If anybody else has run into this particular problem, I would love to hear of a clever way to solve it. I will post my code below.

Note: This particular page is unavailable to the general public, and I am aware there are a few gaping security holes.


require_once 'oo/Database.php';

$mysqldb = new Database;

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect to memcache");

$sql = "SELECT DISTINCT `Genus` FROM importlist.plants";

$key = md5('query'.$sql);

$result = $memcache->get($key);


//check if we got something back
if($result == null) {

    //fetch from database
    $result = $mysqldb->rawSelect($sql)->getResult();

    //set to memcache, expires after 1 hour
    $memcache->set($key,$result,0,3600); 
}

//Result array
$Genera = ($memcache->get($key));

//Add required "quotation marks" for autocomplete
foreach ($Genera as &$Genus){
    $Genus = '"'.$Genus[Genus].'"';
} 
$Genera = implode($Genera,',');

//PHP to generate jQuery    
echo <<< EOT

    <script>
    $(function() {
        var availableTags = [$Genera];
        $( "#tags" ).autocomplete({
            source: availableTags
        });
    });
    </script>
EOT;

?>

<input id="tags" />
like image 760
Ryan Ward Avatar asked Feb 29 '12 01:02

Ryan Ward


2 Answers

$(document).ready(function() {

    // once page loads, make AJAX request to get your autocomplete list and apply to HTML
    $.ajax({ url: '/path-to-get-tags-as-json.php',
        type: "GET",
        contentType: "application/json",
        success: function(tags) {
            $( "#tags" ).autocomplete({
                source: tags
            });
        }
    });
});

Place the URL to your PHP file at generates the autocomplete list in the above AJAX placeholder url parameter. In your PHP code, modify the list generation so that it returns a JSON array of values like so:

[ "first" , "second" , "anotherEntry" , "in" , "the" , "array" ]    

This will definitely not speed up the process server side, but it will protect your users from some of the delays in applying the autocomplete list. This largely assumes that the user doesn't instantly go perform an action that requires autocomplete, you can still load the page and allow the user to perform other actions. The loading of the autocomplete list should for the most part appear silent and seamless.

This is great for load times that are less than a few to several seconds, but if it's taking you longer than that then your users may still run into usability trouble.

If there are still server-side delays, consider using some timing statements to try and determine where the bottleneck is.

like image 173
jmort253 Avatar answered Sep 27 '22 18:09

jmort253


Since you can't lookup anything until the user types at least 1 character, you can create 26 different lists. Each autocomplete list only contains the items that begin with that letter. Your lists will be significantly smaller and faster to load.

To make it even faster, create more lists. You probably only need the first 30-40 items to display. If the item isn't in the shortened list, the user will very likely type another letter. You can then divide your lists up into 26*26 unique lists. Each list containing only items that begin with the first 2 letters.

You can divided your items up into as many lists as needed. We do this on a site I manage where we have over 500K items available in our typeahead.

like image 25
Brent Baisley Avatar answered Sep 27 '22 16:09

Brent Baisley