The app I am making is almost complete, however I am seeing a memory increase every 15 seconds until the app crashes. It increases ~10mb/15seconds.
The app is pretty simple.
I call a repeating timer in applicationDidFinishLaunching as shown here:
timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: "refreshIpAddresses", userInfo: nil, repeats: true)
the timer calls a function called refreshIpAddresses() which calls 3 more functions. This is show below:
func refreshIpAddresses() {
getPrivateIp()
getIpData()
getDnsData()
}
Each of these are similar, so I will just demo one of them. The code below is the method getDnsData().
func getDnsData() {
Alamofire.request(.GET, dataSourceURL2!)
.responseJSON { response in
if (response.result.value != nil) {
let json2 = JSON(response.result.value!)
let json3 = json2["dns"]
let geo = json3["geo"].stringValue
let ip = json3["ip"].stringValue
self.dnsIp.title = "DNS IP: " + ip
self.dnsName.title = "DNS Name: " + geo
} else {
self.dnsIp.title = "No Internet Connection"
self.dnsName.title = "No Internet Connection"
}
}
}
If I comment out the timers, the memory increase stops being an issue.
Is my timer somehow storing information every loop? Should it be invalidated somewhere? Is it my getDnsData() method?
Please help.
EDIT It might not be due to the NSTimer. Can someone guide me how to figure out what the issue is?
Here is the memory leak checks in instruments:
Related
This question follows a previous one that I asked : Trust Querying Event in Ethereum.
In my back-end I listen for an event after a specific transaction. My back-end get the event just after the transaction is added to a new block. However to be sure that the block will not be removed we need to wait that its statut becomes 'finalized'.
My question is : how can I manage to do it using ethersjs ?
Thanks,
I am just poking around stackoverflow for the first time and noticed your question. Since you're building automation around event monitoring, I wanted to recommend a great, free tool that handles this issue around block finality before exposing the event data you need via REST API.
https://www.hal.xyz/products/hal-stream
Hopefully it is helpful :)
I didn't manage to find an ideal solution. However I tried something like this and it seems to work :
provider.on(filter,async (log) => {
const listener ={
async action(){
try{
let iface = new ethers.utils.Interface(abi)
let amount = iface.parseLog(log).args.tokens;
let blockHash = log.blockHash;
let transactionHash = log.transactionHash;
let removed = log.removed;
if(!removed){
this.executedPayment = await ExecutedPayment.create(
{
PaymentId:uuid,
Amount:ethers.utils.formatUnits(amount, DECIMAL_USDT),
TransactionHash:transactionHash,
BlockHash:blockHash,
StateId:1
}
)
clearTimeout(this.finalizationTimeout);
this.finalizationTimeout = setTimeout(async () => {
await this.executedPayment.update({StateId:2})
await this.executedPayment.save()
provider.off(filter)
}, 900000) //if no reorgs happened in the last 15 minutes, we consider the block as finalized
}else{
this.executedPayment.update({StateId:3})
clearTimeout(this.finalizationTimeout);
}
}catch(e){
console.log("An error occured : "+e)
}
}
}
listener.action()
})
If you have another solution I'll be glad to know.
In my app I have a UICollectionView that get data from a server and shows cells with an image and user name and comment.
Every time a user posts a new image and comment a new cell is created. Right now, the UICollectionView shows the new feed just if I reload the view 2 times.
I was wondering if there is a way to update the data in the user’s interface as it changes. Without refreshing the app actually like Facebook app does?
i have been updating like this
override func viewDidLoad() {
super.viewDidLoad()
var timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "callbackFunction", userInfo: nil, repeats: true)
}
internal func callbackFunction() {
// do your busines logic
}
I have a function which uses NSJSONSerialization.JSONObjectWithData, but some memory was not released.
So I tracked down where the leak occurred and tested it with the following function:
private func test() {
for var i = 0; i < 100000; i++ {
let toParse = NSString(string: "{ \"Test\" : [ \"Super mega long JSON-string which is super long because it should be super long because it is easier to see the differences in memory usage with a super long JSON-string than with a short one.\" ] }").dataUsingEncoding(NSUTF8StringEncoding)!
let json = try! NSJSONSerialization.JSONObjectWithData(toParse, options: NSJSONReadingOptions(rawValue: 0))
}
}
The memory-usage of my app before I called test() was 11 MB, the memory-usage after was 74.4 MB (even if I did some other things in my app to give the system some time to release the memory)...
Why is json not released?
Mundi pointed me to autoreleasepool which I hadn't tried yet (insert facepalm here)... so I changed the code to:
autoreleasepool {
self.test()
}
This didn't make any difference, and because Xcode suggested it, I also tried:
autoreleasepool({ () -> () in
self.test()
})
But this also didn't work...
P.S.: Maybe I should add that I'm using Swift 2.0 in Xcode 7 GM.
P.P.S: The test()-function is called from within a
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), {
//... my code ...
self.test()
})
but this shouldn't make any difference...
You are misunderstanding how an autorelease pool works. An autorelease pools keeps hold of allocated memory until the pool is released. Calling a loop 100,000 times inside an autorelease pool means the pool has no chance to release anything, so the memory builds up. Eventually it goes away, when the code has finished running and the autorelease pool is released, but meanwhile your memory usage goes up.
Correct way:
private func test() {
for var i = 0; i < 100000; i++ {
autoreleasepool {
stuff
}
}
}
As you point out in your question, the app arbitrarily releases the memory, so the fact that it is still not release does not mean it would cause a tight memory condition.
You can try enclosing your test routine in an autoreleasepool, similar to Objective-C.
func test() {
autoreleasepool {
// do the test
}
}
I have a Flex app that connects to a JBoss/MS-SQL back-end. Some of our customers have a proxy server in front of their JBoss with a timeout of 90 seconds. In our application there are searches that can take up to 2-3 minutes for complex criteria. Since the proxy isn't smart enough to recognize AMF's keep alive pings for what they are the proxy sends a 503 to the client, which in Flex land becomes a "Channel Call Failed" event. In searching SO and other places, this seems to be a common problem. We can't do anything about the proxy or lengthen the timeout, the application needs to handle it.
Of course the back-end continues to process and eventually ships the results to the client. But the user gets an ugly error message and assumes the app is broke.
The solution I have settled on is to consume the CCF error and have the client continue to wait. I have managed the first part, but I can't figure out how to keep the client's handlers active to receive the data (and/or consume another timeout if necessary).
Current error handler:
private function handleSearchError(event : FaultEvent) : void {
if (event.fault.faultCode == "Channel.Call.Failed") {
event.stopImmediatePropagation(); // doesn't seem to help
return;
}
if (searchProgress != null) {
PopUpManager.removePopUp(searchProgress);
searchProgress = null;
}
etc...
}
This is the setup:
<mx:Button id="btnSearch" label="
{resourceManager.getString('recon_perspective',
'ReconPerspective.ReconView.search')}" icon="{iconSearch}"
click="handleSearch()" includeIn="search, default"/>
And:
<mx:method name="search" result="event.token.resultHandler(event);"
fault="handleSearchError(event);"/>
Kicking off the call:
var token : AsyncToken = null;
token = sMSrv.search(searchType.toString(), getSearchMode(), criteria,
smartMatchParent.isArchiveMode);
searchProgress = LoadProgress(PopUpManager.createPopUp
(FlexGlobals.topLevelApplication as DisplayObject, LoadProgress, true));
searchProgress.title = resourceManager.getString('matching', 'smartmatch.loading.trans');
searchProgress.token = token;
searchProgress.showCancelButton = true;
PopUpManager.centerPopUp(searchProgress);
token.resultHandler = handleSearchResults;
token.cancelSearch = false;
So my question is how do I keep handleSearch and handleSearchError alive to consume the events from the server?
I verified that the data comes back from the server using WebDeveloper in the browser to watch the network traffic and if you cause the app to refresh that screen, the data gets displayed.
I'm very in experienced but would this help?
private function handleSearchError(event : FaultEvent) : void {
if (event.fault.faultCode == "Channel.Call.Failed") {
event.stopImmediatePropagation(); // doesn't seem to help
if(event.isImmediatePropagationStopped(true)) {
//After stopped do something here?
}
return;
}
if (searchProgress != null) {
PopUpManager.removePopUp(searchProgress);
searchProgress = null;
}
etc...
}
I'm using HttpClient from WP8 and do a Post request. I know the call may take long time as I'm actually simulating slow network scenarios. Therefore I set the HttpClient.Timeout accordingly to 5 minutes.
However, I get a Timeout at around 60s. I believe the Timeout is not working.
I believe there is an issue with this for WP as stated in this question:
HttpClient Portable returns 404 notfound on WP8.
They use a workaround but that does not applies to my scenario. I do actually want to wait for long time.
My questions:
1) Is it a bug/issue of HttpClient for WP8 or I'm not setting it properly?
2) Do you think of a workaround still using HttpClient?
I've read that maybe HttpWebRequest is an option. However, I believe HttpClient should be ideal for this 'simple' scenario.
My code is simple:
private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
var client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(5);
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}
The server receives the request and while is processing it, the client aborts.
UPDATE: The HttpResponseMessage returned by HttpClient.PostAsyn is this "{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}". As I said, the server is found and is receiving the data and processing it.
After some search and some tests I've came to the conclusion that the problem is Windows Phone itself and that it has a 60 seconds timeout (irrespective of the HttpClient) and that cannot be changed to my knowledge. See http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.
As I'm programming the server as well, I will try the advice by Darin Rousseau in the link provided above, specifically to send an OK and then do some more processing.
UPDATE: The problem seems to be the Windows Phone emulator as stated here:
http://social.msdn.microsoft.com/forums/wpapps/en-us/6c114ae9-4dc1-4e1f-afb2-a6b9004bf0c6/httpclient-doesnt-work-on-windows-phone?forum=wpdevelop. In my experience the tcp connection times-out if it doesn't hear anything for 60s.
Therefore my solution is to use the Http header characters as a way of keep alive. The first line Http header response always starts with HTTP/1.0. So I send the characters one by one with a delay <60s between them. Of course, if the response gets ready, everything that is left is sent right away. This buys some time, for instance if using a delay of 50s per 9 character we get about 450s.
This is a project for my degree so I wouldn't recommend it for production.
By the way, I also tried with other characters instead the sub string of the header, for instance space character, but that results in a http protocol violation.
This is the main part of the code:
private const string Header1 = #"HTTP/1.0 ";
private int _keepAliveCounter = 0;
private readonly object _sendingLock = new object();
private bool _keepAliveDone = true;
private void StartKeepAlive()
{
Task.Run(() => KeepAlive());
}
/// <summary>
/// Keeps the connection alive sending the first characters of the http response with an interval.
/// This is a hack for Windows Phone 8 that need reponses within 60s interval.
/// </summary>
private void KeepAlive()
{
try
{
_keepAliveDone = false;
_keepAliveCounter = 0;
while (!_keepAliveDone && _keepAliveCounter < Header1.Length)
{
Task.Delay(TimeSpan.FromSeconds(50)).Wait();
lock (_sendingLock)
{
if (!_keepAliveDone)
{
var sw = new StreamWriter(OutputStream);
sw.Write(Header1[_keepAliveCounter]);
Console.Out.WriteLine("Wrote keep alive char '{0}'", Header1[_keepAliveCounter]);
_keepAliveCounter++;
sw.Flush();
}
}
}
_keepAliveCounter = 0;
_keepAliveDone = true;
}
catch (Exception e)
{
// log the exception
Console.Out.WriteLine("Error while sending keepalive: " + e.Message);
}
}
Then, the actual processing happens in a different thread.
Comments and critics are appreciated.
It is possible that you are hitting the timeout of the network stream. You can change this by doing,
var handler = new WebRequestHandler();
handler.ReadWriteTimeout= 5 * 60 * 1000;
var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromMinutes(5);
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
The default on the desktop OS is already 5mins. However, it is possible that on Windows Phone it has been reduced by default.