I am running into what looks like a memory leak on Android using Appcelerator. I am making an HTTP GET call repeatedly until all data is loaded. This call happens about 50 times, for a total of roughly 40 MB of JSON. I am seeing the memory usage spike dramatically if this is executed. If I execute these GETs the heap size (as reported by Android Device Monitor, the preferred method to check memory according to the official Appcelerator docs) gets up to ~240 MB and stays there for as long as the app runs. If I do not execute these GETs, it only uses about 50 MB. I don't think this is a false heap reading either, because if I execute the GETs again (from page 1) I run out of memory.
I have looked through the code and cannot find any obvious leaks, such as storing all results in a global variable or something. Are the HTTP responses being cached somewhere?
Here is my code, for reference. syncThings(1, 20) (sanitized name :) ) gets called during startup. It in turn calls a helper function syncDocuments(). Here are the two functions. Don't worry about launchMainWindow() unless you think it could be relevant, but assume it does no cleanup.
function syncThings(page, itemsPerPage) {
var url = "the_url";
console.log("Getting page " + page);
syncDocuments(url,
function(response) {
if (response.totalDocumentsInQuery == itemsPerPage) {
// More pages to get
setTimeout(function() {
syncThings(page + 1, itemsPerPage);
}, 1);
} else {
// This was the last page
launchMainWindow();
}
},
function(e) {
Ti.API.error('Default error callback called for syncThings;', e);
dispatcher.trigger('app:update:stop');
});
}
function syncDocuments(url, successCallback, errorCallback) {
new HTTPRequest({
url: url,
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
timeout: 30000,
success: function (response) {
Ti.API.info('Success callback called for ' + url);
successCallback(response);
},
error: function (error) {
errorCallback(error);
}
}).send();
}
Any ideas? Am I doing something wrong here?
Edit: I am using Titanium SDK 6.0.1.GA. This happens on all Android versions.
Try using the file-property of the HTTPClient: http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Network.HTTPClient-property-file
otherwise the file will be loaded into memory.
There will be a memory leak fix in 6.1.0: https://github.com/appcelerator/titanium_mobile/pull/8818 that might fix something too.
Related
While delete a comment, I can delete two comments back to back but when I tried to delete next comment(3rd comment). It shows error in console “Rate limited due to excessive requests.” But after few seconds when I try to delete, it works fine for next two comments. I have tried to use “wait” function for few seconds to make it work but there is inconsistency in result. Sometimes it works and sometimes it doesn’t.
My code as follows,
function deleteComment(MessagePostId) {
var result = confirm("Are you sure you want to delete this Comment?");
if (result) {
yam.platform.request({
url: "https://api.yammer.com/api/v1/messages/" + MessagePostId,
method: "DELETE",
async: false,
beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', token) },
success: function (res) {
alert("The Comment has been deleted.");
//Code to remove item from array and display rest of the comment to screen
},
error: function (res) {
alert("Please try again after some time.");
}
})
}
}
You are hitting rate limits which prevent multiple deletion requests from a regular user like those which you've hit. The API is designed for client applications where you perhaps make an occasional deletion, but aren't deleting in bulk.
To handle rate limits, you need to update your code to check the response value in the res variable. If it's an HTTP 429 response then you are being rate limited and need to wait before retrying the original request.
I'm using a Web App (which is really big) so there are some parts of the application that I really don't know how they work.
I am a front end developer and I'm consuming a REST API implemented with .NET Web Api (as far as I know)
The request is simple - I use kendo Datasource to get the data from the server like this
var kendoDataSource = new kendo.data.DataSource({
// fake transport with local data
transport: {
read: function(options) {
// set results
options.success(lookupValues);
}
},
schema: {
parse: function (response) {
// sort case insensitive by name
response.sort(function (a, b) {
return (a.Name.toLowerCase() > b.Name.toLowerCase()) ? 1 : (a.Name.toLowerCase() < b.Name.toLowerCase()) ? -1 : 0;
});
return response;
}
},
// set the page size
pageSize: 25
});
and the request for the data
$http({ method: 'GET', url: 'REST/SystemDataSet/' + id + '/Values' }).success(function (response) {
// store data
lookupValues = response;
kendoDataSource.read();
// do some logic here
}).error(function(error) {
// logic
});
I do this in this way because there is some extra logic that manipulates the data.
This request in Chrome takes like 32 ms while it takes almost 9 seconds in IE.
The data retrieved is the same (you can see the Size of response), which is an array of JSon objects (Very simple)
I don't know exactly if there is a cache mechanism in the backend, but it shouldn't matter because I'm able to reproduce it like this every time (fast in Chrome, really really slow on IE)
Any ideas of what could be causing this behaviour ? As I understand, if there is a cache or something, it should be the same for every browser, so this should be happening on both and not only on IE - the backend is agnostic of the browser.
Here is some extra information I have from another request to check the distribution of time in the first IE request
As you can see, the biggest part is the "Request", which is the Time taken to send the request and receive the first response from the server.
Thanks in Advance
The problem is probably Windows Authentication turned on for the folder you are calling the ajax from...
Same principle applies here ...
http://docs.telerik.com/kendo-ui/web/upload/troubleshooting
Problem: Async uploads randomly fail when using IE10/11 with Windows Authentication
The upload either freezes indefinitely or times out if a 401 challenge is received on the HTTP POST.
Solution
For IE10 see KB2980019
No official fix for IE 11 as of November 6, 2014. See bug ID 819941
I am trying to send data to server using ajax, but the problem is that I have a consuming process before sending the data.
The process takes about 5 seconds and the spinner has to run in the process.
So in my code the spinner doesnt show until the ajax call starts (probably because the process is blocking everything)
If I move the call "consumingprocess" into "beforesend", then it doesnt work and I am not sure why.
So the question is how to show the spinner, while everything is beeing called (the consumingprocess and the ajax call)
Thanks
This is my code:
$("#btnAccept").bind("click", function(event, ui) {
//start spinner, works fine but only shows after consumingprocess has finished
$.mobile.loading( 'show' );
console.log("btnAccept");
var data = consmuingprocess();
console.log(data);
// data is fine
$.ajax({
type : "POST",
url : url,
dataType : "xml",
contentType : "text/xml;charset=UTF-8",
data : data,
requestHeaders : {
Origin : '*'
},
crossDomain : true,
beforeSend : function(xhr) {
xhr.setRequestHeader("Authorization", "Basic xxxxxxxxxxxxxxx");
console.log("beforeSend");
},
error : errorAJAX,
success : parseXml
});
});
});
What you can do is
call your loading window
delay so the loading window has a chance to display
run the rest of your code.
You would do this using an interval:
$("#btnAccept").bind("click", function(event, ui) {
var intervalId;
function delayedStuff = function() {
// make sure we only run this once
window.clearInterval(intervalId);
var data = consmuingprocess();
$.ajax({
// set up your ajax request and handlers
});
};
$.mobile.loading( 'show' );
// wait 1/2 second, then run delayedStuff
intervalId = window.setInterval(delayedStuff, 500);
});
But this technique comes with an important caveat: while your very expensive consumingProcess function is running, all animations and javascript still comes to a halt. On Chrome, even animated gifs stop running. All we've done here is just given your page changes a chance to display.
There are a couple of possible solutions available:
Take a closer look at your consumingprocess() function and see if it can be optimized. There is probably a faster way to do whatever it is you're doing that's taking so long.
Use WebWorkers. The downside is compatibility: IE and most older browsers don't support it. I haven't done multi-threaded programming with JavaScript at all, so I don't know how effective this is.
my web site is made using Ext JS 4.1 framework and ASP .Net MVC v3. When new frame is rendered there are 19 separate AJAX requests for retrieving data in JSON-format. All requests are familiar and made by Ext.Ajax.request(). Example:
Ext.Ajax.request({
url: getOrderLink,
method: "GET",
params: { recId: orderRecId },
headers: {
'Accept': 'application/json'
},
success: function (response) {
var order = Ext.decode(response.responseText);
...
}
});
In some cases there are errors in ext-all.js in
onStateChange : function(request) {
if (request.xhr.readyState == 4) {
this.clearTimeout(request);
this.onComplete(request);
this.cleanup(request);
}
},
where request has no property xhr so that request.xhr.readyState throws exception "Cannot read property 'readState' of undefined".
This errors appear not for all requests and don't effect site work(responses are retrieved successfully). Some times this errors don't appear at all. Timeout for all requests is set to 30s by default and they take about 1.5-2 seconds each.
I am using Google Chrome 21.
Could you please give me some idea why it's happening.
The problem seems to occur if and only if you have a breakpoint or a "debugger;" line in anything related to AJAX. For me it happened in Chrome, haven't tried other browsers yet.
In my case it happened when I had set a breakpoint in a load event handler for a store like code example below.
But the error occurrs if you set a breakpoint inside the Ext onStateChange function in the framework itself as well.
If disabling your breakpoints and debugger; calls removes the error you can safely ignore it!
There is a similar thread on ExtJS forums. Sencha might add a fix.
Ext.define('MyApp.controller.MyController', {
extend: 'Ext.app.Controller',
stores: ['Projects'],
init: function () {
this.getProjectsStore().addListener(
"load",
this.onProjectsStoreLoaded,
this
);
},
onProjectsStoreLoaded: function () {
console.log('MyController: onProjectsStoreLoaded');
debugger; // <- this causes the errors to appear in the console
SomeOtherThingsIWantedToDebug();
}
}
I am displaying a graph using jQplot to monitor data.
To refresh the div holding the graph, I invoke an ajax call every 5 seconds (see JavaScript excerpt below).
On the server, a PHP script retrieves the data from a database.
On success, the ajax call is reinvoked after 5 seconds with a JavaScript setTimeout(ajax,5000).
On error, the ajax call is retried 10 times with setTimeout(ajax,5000) before displaying an error message.
Monitoring XHR learns that the browser crashes after approximately 200 requests.
As a temporary remedy, a location.reload() is issued after 50 iterations to prevent the browser from crashing.
This works, but is not an ideal situation.
Any better solution to this problem is very much appreciated.
Thanks and regards, JZB
function ajax() {
$.ajax({
cache: false,
url: 'monitor.php',
data : { x: id },
method: 'GET',
dataType: 'json',
success: onDataReceived,
error: onDataError
});
function onDataReceived(series) {
$('#chartdiv_bar').html('');
$.jqplot('chartdiv_bar', [series['initHits']], CreateOptions(series,'Inits'));
errorcount = 0;
setTimeout(ajax, 5000);
}
function onDataError(jqXHR, textStatus, errorThrown) {
errorcount++;
if (errorcount == 10) {
alert("No server response:\n\n" + textStatus + "\n" + errorThrown);
} else {
setTimeout(ajax, 5000);
}
}
}
Since you're re-calling ajax() after a good or fail ajax call, you're starting multiple timers. This is why your browser is crashing.
you may want to try to clear the current timer and then start the next timer
var t; //global
In each of your call back functions:
if(t)
clearTimeout(t);
t = setTimeout(ajax, 5000);
more info on timer here: w3 school
I removed the jqplot call as suggested and the problem disappeared.
Apparently jqplot is the culprit and I found numerous entries referring to jqPlot memory leaks.
I use jQuery 1.6.4 and installed jqPlot Charts version 1.0.0b2_r792 which supposedly addresses memory leak issues.
Furthermore, I replaced
$('#chartdiv_bar').html('');
with
$('#chartdiv_bar').empty();
Thank you for your support.