iPhone lagging

You must Login before you can answer or comment on any questions.

I have a program which basically downloads a database from the server at the launch, parses the JSON, and stores it in the memory (it has a few hundred items), then I attach a function to the Location event, filter the location change to 30 m (don't call the following except the moving delta is bigger thant 30 m), then filter this array by the distance of the objects. Of course I have to calculate all distances every time to be able to filter the array and I also have to sort is to be able to display the correct list of values on the screen.

The values are displayed the following way: 1. I initialize a new array, 2. go through the filtered items with for, 3. create a tableviewrow for each filtered item (with my creator function, which sets a few labels on them), 4. push the row into the array created in (1), 5. then set the tableview's content with this array (with the setData()).

This results an incredible lag on the real device (iPhone 4) and some small lag on the Simulator. What do I mean lag? If you click something in an other window of the app, like a button, it opens the corresponding window or does the corresponding function in 15-30 secs. With Instruments I was able to determine that the main reason of this lag is that filtering the datas and refilling the tables uses 100% CPU and multiple requests overlap eachother. To be more specific, Titanium's Garbage Collector uses the most CPU cycles, almost the 95% of the time.

How do I supposed to update a table if not this way? Is it maybe anything other than this wrong? What do you think?

If you prefer, I can post code quotes and a video demonstrating the lag.

— asked 1 year ago by Kristof Gruber
4 Comments
  • More is always better if you can post code, example.

    — commented 1 year ago by Ray Belisle

  • Hello, as a thumb rule, try to fill the data array in advance and then update or add them to the table in chunks of 10 or 20, don't try to fill all the results in the table at once. Display some info (maybe one screen -- current screen -- and keep the next page to display in memory).

    Best,

    Mauro

    — commented 1 year ago by Mauro Parra

  • Can you perform your geo filtering on the server first ? ie Get the geo and then make the call for the content and filter server-side ? Anything that takes the load off the the phone is a good thing

    — commented 1 year ago by Nick Milner

  • Show 1 more comment

3 Answers

Here is some parts of my code which I belive has something to do with the high CPU usage.

This is the first function, which filters traffipaxes by date (also does a little bit workaround because our client provides not always the best databases…):

traffi.utils.filterActualTraffipaxes = function(p) {
    var filteredTraffipaxes = [];
 
    var now = new Date();
 
    for (var i in p.traffipaxes) {
        var start_date = new Date(parseInt(p.traffipaxes[i].start_date_ts) * 1000);
 
        if (start_date < now) {
            var found = false;
 
            p.traffipaxes[i].description = p.traffipaxes[i].description.trim();
 
            for (var j in filteredTraffipaxes) {
                if (p.traffipaxes[i].description == filteredTraffipaxes[j].description) {
                    found = true;
                }
            }
 
            if (!found) {
                if (traffi.fixTraffipaxes) {
                    filteredTraffipaxes.push(p.traffipaxes[i]);
                } else {
                    if (p.traffipaxes[i].fix == false) {
                        filteredTraffipaxes.push(p.traffipaxes[i]);
                    }
                }
            }
        }
    }
 
    return filteredTraffipaxes;
};
Here is the one which adds the distances to the objects:
traffi.utils.addDistances = function(traffipaxes) {
    for (var i in traffipaxes) {
        var currentDistance = traffi.utils.calculateDistance({
            longitude: traffipaxes[i].longitude,
            latitude: traffipaxes[i].latitude
        }, traffi.coords);
        traffipaxes[i].distance = currentDistance;
    }
};
This one is for filtering the datas by distance.
traffi.utils.filterByDistance = function(p) {
    var filteredTraffipaxes = [];
 
    if (traffi.coords == null) {
        return [];
    }
 
    for (var i in p.traffipaxes) {
        if (p.traffipaxes[i].distance <= p.distance) {
            filteredTraffipaxes.push(p.traffipaxes[i]);
        }
    }
 
    return filteredTraffipaxes;
};

try to store in sqlite, and run query from database, hopefully its better:)

Thanks for the comments. I did a rewrite of the complete model logic of my program, and used SQL database instead of memory variables. This way I could achieve 2-10x speed bump. The only slow function is now the one which updates the distances with SQL into the database.

Another interesting thing I've found (and it might help others, so share with you): It seems that Titanium queues the events in the program in one big line. So if the location changes, Titanium puts the event's callback in the queue, which is invoked when the queue achieves that point. This way it is possible that your callback runs longer than the period of the location update, so after a time it will be lagging anyways.

My solution: my event callback receives a timestamp as a parameter, which tells the function it's calling time. If the execution time is lagging more than a treshold time delta compared to this parameter, I refuse to run the function and return.

— answered 1 year ago by Kristof Gruber
answer permalink
1 Comment
  • I've found that my solution does not work, because even the calling is delayed, so the time delta is only a few msecs.

    — commented 1 year ago by Kristof Gruber

Your Answer

Think you can help? Login to answer this question!