We used this script to get, and filter a JSON with 100.000 elements, to make some quick search at user-side, but unfortunately this is not fast enough.
What do you think, how can i make this script run faster?
<script>
$(document).ready(function () {
var data__ = new Array();
var val__ = new Array();
var val_sum = 0;
$.ajax({
url: 'hotel.php',
type: 'POST',
dataType: 'json',
timeout: 5000,
beforeSend: function () {
}, error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responseText);
alert(thrownError);
return false;
},
success: function (data)
{
var list = JSLINQ(data)
.Where(function(item){ return item.regio == "Afrika"; })
.OrderBy(function(item) { return item.name; })
.Select(function(item){ return item; });
var movies = list['items']
var markup = "<tr><td colspan='2'><b>Hotel: </b> ${name}</td><td><b>Régió:</b> ${regio}</td><td><b>Orszag:</b> ${orszag}</td><td><b>Város:</b> ${varos}</td></tr>";
/* Compile markup string as a named template */
$.template( "movieTemplate", markup );
/* Render the named template */
$( "#movieList" ).empty();
$.tmpl( "movieTemplate", movies ).appendTo( "#movieList" );
}
});
return false;
});
</script>
Thanks for the help.
You are returning items where region indicates "Afrika". Note that spelling of 'Afrika' could be 'Africa' and that you may still get a lot of items even when you get a timeout. In the database, make sure that the table is properly indexed to make the where and orderby as fast as possible.
Surely you want to apply the logic that JSLinq is doing on the server side.
So on the serverside only return results where Name='Afrika'
and order the results by name
. Then you don't have the overhead of JSLinq filtering and ordering all of your results.
This would produce.
I'm going to propose some general enhancements (item #1) and some specific (rest of them). You can pick and choose which ones you want to go with.
success
call. Move them outside of success
.Rewriting your code with underscore JS:
<script>
$(document).ready(function () {
var data__ = [];
var val__ = [];
var val_sum = 0;
var markup = "<% _.each(items, function(item) { %><tr><td colspan='2'><b>Hotel: </b> <%= item.name %></td><td><b>Régió:</b> <%= item.regio %></td><td><b>Orszag:</b> <%= item.orszag %></td><td><b>Város:</b> <%= item.varos %></td></tr><% }); %>";
var compiledTemplate = _.template(markup);
$.ajax({
url: 'hotel.php',
type: 'POST',
dataType: 'json',
timeout: 5000,
beforeSend: function () {
}, error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responseText);
alert(thrownError);
return false;
},
success: function (data)
{
var list = _(data)
.chain()
.select(data, function(item){ return item.regio == "Afrika"; })
.sortBy(function(item) { return item.name; })
.value();
var movies = list['items']
/* Render the named template */
$( "#movieList" ).empty().append(compiledTemplate(movies));
}
});
return false;
});
</script>
The biggest improvement can be seen on the slowest browser - IE7. This code should be 10 times (approx) faster than you existing code, but do profile them to get exact figures.
I would guess that most of the time is spent executing the LINQ-query. I'd suggest that you run the code through a javascript profiler, like Profiles
in Google Chrome to locate cumbersome operations.
Also, === might at times be faster than == as the former does not perform type conversion, which you might benefit from when traversing larger collections. Also using the profiler, see if there are any benefits by using raw javascript code to perform the operations:
var result = [];
for (var d in data) { // or regular for (var i = 0; ...
if (d.regio === "Afrika") {
result.push(d); // or result[result.length] = d;
}
}
result.sort(function(a, b) {
// sort a.name and b.name
});
I do realise this make minimum use of the jQuery core, but it's a means for you to at least examine the overhead (or optimisation) that the library is offering.
Also try to use regular string concatenation (or array joins depending on what works the best for you) over a fully fledged template engine.