Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Mike Abdullah

 On 13 Jan 2015, at 01:00, Graham Cox graham@bigpond.com wrote:
 
 I'm still having an issue with this - I think.
 
 I've exhaustively hunted down every leak and memory allocation in my app - 
 luckily it's a fairly small one, though one that can create many threads - 
 and have eliminated everything I have control over*
 
 My heap space is still growing over time. I'm having a LOT of trouble 
 understanding how to use Allocations Instrument effectively - I just can't 
 really understand what it's trying to tell me. I have read the documentation 
 for Allocations but it's not really much help, because it's hard for me to 
 'mark generations' when a 'generation' is something that happens as a result 
 of external factors, not a user-interface action.
 
 I've satisfied myself that possible issues to do with blocks causing 
 potential retain cycles are definitely not the issue, nor is fumbling my way 
 using ARC for the first time**.
 
 What I'm left with is either a genuine memory leak that occurs inside the 
 CFNetwork framework, or an apparent memory leak that isn't one really that I 
 can safely ignore. I'm just not sure which.
 
 To recap, what my app does is to record chunks of video data to a file using 
 NSURLSession and NSURLSessionDataTask. These chunks are obtained by parsing a 
 .m3u8 playlist file. Each 'chunk' is a unique URL which is generated by the 
 server and persists for a fairly short time. By concatenating the data 
 returned by each fetch of these URLs, a complete capture of a live stream is 
 achieved. Overall, this process works great with the nagging problem of 
 growing memory usage. This growth appears to be somewhat related (but not 
 exactly correlated with) the amount of data downloaded and recorded. For 
 example, at first the leak is somewhat larger than what I record, but over 
 time it becomes quite a bit smaller. However if I record nothing, there is no 
 leak. What concerns me is that the leak can get large - after a day or so 
 of running, it's getting up to 3GB for example.
 
 In my NSURLSessionConfiguration, I have turned off the URLCache (set it to 
 nil) - there's no purpose to caching data for the chunks because they are 
 only ever accessed once. Similarly I've disabled cookies. What I should be 
 looking at is a straightforward uncached download of a URL, write that data 
 to disk and move on. Here's my config setup:
 
   self.configuration = [NSURLSessionConfiguration 
 ephemeralSessionConfiguration];
   NSDictionary* additionalHeaders = 
 @{@User-Agent:XViPadUserAgentString};
   self.configuration.HTTPAdditionalHeaders = additionalHeaders;
   
   self.configuration.HTTPCookieAcceptPolicy = 
 NSHTTPCookieAcceptPolicyNever;
   self.configuration.HTTPCookieStorage = nil;
   self.configuration.URLCache = nil;
   
   self.session = [NSURLSession 
 sessionWithConfiguration:self.configuration];

One small suggestion: I think the frameworks would prefer it if you copied the 
ephemeralSessionConfiguration, and then modified the copy. Modifying this 
shared config is probably not supported, and while it might work now, might not 
in future.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Kevin Meaney
leaks, not bugs.

Kevin

On 13 Jan 2015, at 10:21, Kevin Meaney k...@yvs.eu.com wrote:

 On 13 Jan 2015, at 02:51, Graham Cox graham@bigpond.com wrote:
 
 On 13 Jan 2015, at 12:21 pm, Roland King r...@rols.org wrote:
 
 Did you read the devforums thread I pointed you at a couple of weeks ago?
 
 
 Umm, not sure Roland. I read the blog post by bbum about using Allocations, 
 which is the one you linked in this thread. Did you mean something else? 
 Forgive me, I can't locate the link if so.
 
 If you're referring to bbum's post, I read that. I'm assuming that 
 heapshot is now labelled mark generations but otherwise is the same 
 thing. The problem with this in my case is that a generation is a new URL 
 download and that's fired off automatically by either the previous one 
 completing or a timer that's set to a variable time based on the target 
 time of the playlist entry. There's no clear means for me to hit mark 
 generation at exactly the right time. That might not matter all that much 
 in that the process is continuous, so as long as I'm downloading a stream at 
 a fairly steady rate, and hit the button at regular intervals, there should 
 be a reasonable similarity between runs.
 
 Doing that, I get inconclusive results. Most of the memory that is left is 
 like this:
 
 Snapshot Timestamp   Growth  # Persistent
 Generation B 01:32.780.375   2.09 MB 38
 VM: Performance tool data2.08 MB 4
 0x116816000  01:13.421.801   532.00 KB
 0x1162ed000  01:32.145.259   532.00 KB
 0x11614  01:23.051.011   532.00 KB
 0x1161e5000  01:02.847.030   532.00 KB
 
 
 Which suggests it's memory allocated by Allocations itself.
 
 But where I'm checking this over longer time periods isn't in Instruments at 
 all, but in Xcode's memory viewer. Unfortunately that doesn't give me a 
 breakdown, just an overall usage.
 
 I went through a similar painful process in early November hunting down bugs. 
 I'm not using NSURLConnection so I can't really comment about that API and 
 I'm working on OS X. This comment and the remarks a little later in this 
 thread referring to Quinn triggered a recollection.
 
 In desperation I looked at things using Activity Monitor's memory section and 
 turned on the columns Real Mem, Shared Mem, and Purgeable Mem. In my case 
 what I was seeing as a leak matched with the memory marked as purgeable.
 
 Exactly what is meant by purgeable I don't know beyond the obvious.
 
 Kevin
 
 
 
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/ktam%40yvs.eu.com
 
 This email sent to k...@yvs.eu.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Kevin Meaney
On 13 Jan 2015, at 02:51, Graham Cox graham@bigpond.com wrote:
 
 On 13 Jan 2015, at 12:21 pm, Roland King r...@rols.org wrote:
 
 Did you read the devforums thread I pointed you at a couple of weeks ago?
 
 
 Umm, not sure Roland. I read the blog post by bbum about using Allocations, 
 which is the one you linked in this thread. Did you mean something else? 
 Forgive me, I can't locate the link if so.
 
 If you're referring to bbum's post, I read that. I'm assuming that heapshot 
 is now labelled mark generations but otherwise is the same thing. The 
 problem with this in my case is that a generation is a new URL download and 
 that's fired off automatically by either the previous one completing or a 
 timer that's set to a variable time based on the target time of the 
 playlist entry. There's no clear means for me to hit mark generation at 
 exactly the right time. That might not matter all that much in that the 
 process is continuous, so as long as I'm downloading a stream at a fairly 
 steady rate, and hit the button at regular intervals, there should be a 
 reasonable similarity between runs.
 
 Doing that, I get inconclusive results. Most of the memory that is left is 
 like this:
 
 Snapshot  Timestamp   Growth  # Persistent
 Generation B  01:32.780.375   2.09 MB 38
 VM: Performance tool data 2.08 MB 4
  0x116816000  01:13.421.801   532.00 KB
  0x1162ed000  01:32.145.259   532.00 KB
  0x11614  01:23.051.011   532.00 KB
  0x1161e5000  01:02.847.030   532.00 KB
 
 
 Which suggests it's memory allocated by Allocations itself.
 
 But where I'm checking this over longer time periods isn't in Instruments at 
 all, but in Xcode's memory viewer. Unfortunately that doesn't give me a 
 breakdown, just an overall usage.

I went through a similar painful process in early November hunting down bugs. 
I'm not using NSURLConnection so I can't really comment about that API and I'm 
working on OS X. This comment and the remarks a little later in this thread 
referring to Quinn triggered a recollection.

In desperation I looked at things using Activity Monitor's memory section and 
turned on the columns Real Mem, Shared Mem, and Purgeable Mem. In my case what 
I was seeing as a leak matched with the memory marked as purgeable.

Exactly what is meant by purgeable I don't know beyond the obvious.

Kevin





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Graham Cox

 On 13 Jan 2015, at 8:11 pm, Mike Abdullah mabdul...@karelia.com wrote:
 
 One small suggestion: I think the frameworks would prefer it if you copied 
 the ephemeralSessionConfiguration, and then modified the copy. Modifying this 
 shared config is probably not supported, and while it might work now, might 
 not in future.


My reading of the docs is that these convenience methods create new objects, 
not return shared ones. I'll check again, though.

--Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Mike Abdullah

 On 13 Jan 2015, at 13:05, Graham Cox graham@bigpond.com wrote:
 
 
 On 13 Jan 2015, at 8:11 pm, Mike Abdullah mabdul...@karelia.com wrote:
 
 One small suggestion: I think the frameworks would prefer it if you copied 
 the ephemeralSessionConfiguration, and then modified the copy. Modifying 
 this shared config is probably not supported, and while it might work now, 
 might not in future.
 
 
 My reading of the docs is that these convenience methods create new objects, 
 not return shared ones. I'll check again, though.

Upon a re-read, I think you’re probably right. The docs for 
+defaultSessionConfiguration are certainly clear on the subject, and it seems 
to reasonable to assume +ephemeralSessionConfiguration follows the same 
behaviour.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-13 Thread Jens Alfke
May I just jump in to say that you probably should be discussing this on the 
macnetworkprog list? There are people on that list (esp. Quinn) who are experts 
in this area.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Graham Cox
I'm still having an issue with this - I think.

I've exhaustively hunted down every leak and memory allocation in my app - 
luckily it's a fairly small one, though one that can create many threads - and 
have eliminated everything I have control over*

My heap space is still growing over time. I'm having a LOT of trouble 
understanding how to use Allocations Instrument effectively - I just can't 
really understand what it's trying to tell me. I have read the documentation 
for Allocations but it's not really much help, because it's hard for me to 
'mark generations' when a 'generation' is something that happens as a result of 
external factors, not a user-interface action.

I've satisfied myself that possible issues to do with blocks causing potential 
retain cycles are definitely not the issue, nor is fumbling my way using ARC 
for the first time**.

What I'm left with is either a genuine memory leak that occurs inside the 
CFNetwork framework, or an apparent memory leak that isn't one really that I 
can safely ignore. I'm just not sure which.

To recap, what my app does is to record chunks of video data to a file using 
NSURLSession and NSURLSessionDataTask. These chunks are obtained by parsing a 
.m3u8 playlist file. Each 'chunk' is a unique URL which is generated by the 
server and persists for a fairly short time. By concatenating the data returned 
by each fetch of these URLs, a complete capture of a live stream is achieved. 
Overall, this process works great with the nagging problem of growing memory 
usage. This growth appears to be somewhat related (but not exactly correlated 
with) the amount of data downloaded and recorded. For example, at first the 
leak is somewhat larger than what I record, but over time it becomes quite a 
bit smaller. However if I record nothing, there is no leak. What concerns me is 
that the leak can get large - after a day or so of running, it's getting up 
to 3GB for example.

In my NSURLSessionConfiguration, I have turned off the URLCache (set it to nil) 
- there's no purpose to caching data for the chunks because they are only ever 
accessed once. Similarly I've disabled cookies. What I should be looking at is 
a straightforward uncached download of a URL, write that data to disk and move 
on. Here's my config setup:

self.configuration = [NSURLSessionConfiguration 
ephemeralSessionConfiguration];
NSDictionary* additionalHeaders = 
@{@User-Agent:XViPadUserAgentString};
self.configuration.HTTPAdditionalHeaders = additionalHeaders;

self.configuration.HTTPCookieAcceptPolicy = 
NSHTTPCookieAcceptPolicyNever;
self.configuration.HTTPCookieStorage = nil;
self.configuration.URLCache = nil;

self.session = [NSURLSession 
sessionWithConfiguration:self.configuration];

So my question is, has anyone used these classes and seen something similar 
occurring? Is it just one of those things, or am I still doing something 
wrong? At this point I'm just not sure what else I can do. Is some of that URL 
download being cached anyway, despite me telling it not to bother? Is it just 
cache growth I'm seeing and that's being managed elsewhere? Maybe 3GB after a 
day or two is acceptable?

*One of the things I tried in desperation is to turn off ARC and go back to 
manual memory management. Fact is, I'm just more comfortable with MM at the 
moment. I'm not claiming ARC is bad or anything like that, but in trying to 
hunt down the issue, I wanted to have as familiar territory as possible. In 
fact the manual memory management did allow me to discover a few other leaks 
where I'd obviously not told ARC the right thing (e.g. something was not being 
released because it created a timer, and the timer was invalidated in -dealloc, 
which of course doesn't work, even in MM land), but not related to this leak 
problem, which persists.

** See above - there is no ARC now.



 On 2 Jan 2015, at 2:45 pm, Graham Cox graham@bigpond.com wrote:
 What appears to be amassing are 132KB malloc'd blocks (by the hundreds). 
 These are created by 
 HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, unsigned long), 
 down in CFNetwork. The stack trace is:
 
   0 libsystem_malloc.dylib malloc_zone_malloc
   1 libsystem_malloc.dylib malloc
   2 CFNetwork HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, 
 unsigned long)
   3 CFNetwork 
 CFNetworkReadStream::_readStreamClientCallBackCallBack(__CFReadStream*, 
 unsigned long, void*)
   4 CoreFoundation _signalEventSync
   5 CoreFoundation _cfstream_shared_signalEventSync
   6 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
   7 CoreFoundation __CFRunLoopDoSources0
   8 CoreFoundation __CFRunLoopRun
   9 CoreFoundation CFRunLoopRunSpecific
  10 CFNetwork +[NSURLConnection(Loader) _resourceLoadLoop:]
  11 Foundation __NSThread__main__
  12 libsystem_pthread.dylib 

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Roland King
Did you read the devforums thread I pointed you at a couple of weeks ago? I 
noted it was iOS not OSX however my general belief is as time goes by, more and 
more code is common to the platforms so if there’s a bug in iOS at 8.x (and 
there is) it may also exist on OSX at some recent version. On that thread 
someone was doing what you’re doing, scheduling new NSURL requests at the 
completion of the previous one and they were getting constant memory growth. 

I’d also suggest at this point after tearing things apart for quite a while and 
putting them back together again, you might be best served asking DTS for help. 
If you’re lucky Quinn will pick up the ticket, but even if he doesn’t someone 
should actually be able to help you make sense of your allocations traces and 
tell you if there is a current, open bug in NSURLSession. 


 On 13 Jan 2015, at 09:00, Graham Cox graham@bigpond.com wrote:
 
 I'm still having an issue with this - I think.
 
 I've exhaustively hunted down every leak and memory allocation in my app - 
 luckily it's a fairly small one, though one that can create many threads - 
 and have eliminated everything I have control over*
 
 My heap space is still growing over time. I'm having a LOT of trouble 
 understanding how to use Allocations Instrument effectively - I just can't 
 really understand what it's trying to tell me. I have read the documentation 
 for Allocations but it's not really much help, because it's hard for me to 
 'mark generations' when a 'generation' is something that happens as a result 
 of external factors, not a user-interface action.
 
 I've satisfied myself that possible issues to do with blocks causing 
 potential retain cycles are definitely not the issue, nor is fumbling my way 
 using ARC for the first time**.
 
 What I'm left with is either a genuine memory leak that occurs inside the 
 CFNetwork framework, or an apparent memory leak that isn't one really that I 
 can safely ignore. I'm just not sure which.
 
 To recap, what my app does is to record chunks of video data to a file using 
 NSURLSession and NSURLSessionDataTask. These chunks are obtained by parsing a 
 .m3u8 playlist file. Each 'chunk' is a unique URL which is generated by the 
 server and persists for a fairly short time. By concatenating the data 
 returned by each fetch of these URLs, a complete capture of a live stream is 
 achieved. Overall, this process works great with the nagging problem of 
 growing memory usage. This growth appears to be somewhat related (but not 
 exactly correlated with) the amount of data downloaded and recorded. For 
 example, at first the leak is somewhat larger than what I record, but over 
 time it becomes quite a bit smaller. However if I record nothing, there is no 
 leak. What concerns me is that the leak can get large - after a day or so 
 of running, it's getting up to 3GB for example.
 
 In my NSURLSessionConfiguration, I have turned off the URLCache (set it to 
 nil) - there's no purpose to caching data for the chunks because they are 
 only ever accessed once. Similarly I've disabled cookies. What I should be 
 looking at is a straightforward uncached download of a URL, write that data 
 to disk and move on. Here's my config setup:
 
   self.configuration = [NSURLSessionConfiguration 
 ephemeralSessionConfiguration];
   NSDictionary* additionalHeaders = 
 @{@User-Agent:XViPadUserAgentString};
   self.configuration.HTTPAdditionalHeaders = additionalHeaders;
   
   self.configuration.HTTPCookieAcceptPolicy = 
 NSHTTPCookieAcceptPolicyNever;
   self.configuration.HTTPCookieStorage = nil;
   self.configuration.URLCache = nil;
   
   self.session = [NSURLSession 
 sessionWithConfiguration:self.configuration];
 
 So my question is, has anyone used these classes and seen something similar 
 occurring? Is it just one of those things, or am I still doing something 
 wrong? At this point I'm just not sure what else I can do. Is some of that 
 URL download being cached anyway, despite me telling it not to bother? Is it 
 just cache growth I'm seeing and that's being managed elsewhere? Maybe 3GB 
 after a day or two is acceptable?
 
 *One of the things I tried in desperation is to turn off ARC and go back to 
 manual memory management. Fact is, I'm just more comfortable with MM at the 
 moment. I'm not claiming ARC is bad or anything like that, but in trying to 
 hunt down the issue, I wanted to have as familiar territory as possible. In 
 fact the manual memory management did allow me to discover a few other leaks 
 where I'd obviously not told ARC the right thing (e.g. something was not 
 being released because it created a timer, and the timer was invalidated in 
 -dealloc, which of course doesn't work, even in MM land), but not related to 
 this leak problem, which persists.
 
 ** See above - there is no ARC now.
 
 
 
 On 2 Jan 2015, at 2:45 pm, 

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Roland King
https://devforums.apple.com/message/1056669#1056669

No that one from the same mail. 



 On 13 Jan 2015, at 10:51, Graham Cox graham@bigpond.com wrote:
 
 
 On 13 Jan 2015, at 12:21 pm, Roland King r...@rols.org wrote:
 
 Did you read the devforums thread I pointed you at a couple of weeks ago?
 
 
 Umm, not sure Roland. I read the blog post by bbum about using Allocations, 
 which is the one you linked in this thread. Did you mean something else? 
 Forgive me, I can't locate the link if so.
 
 If you're referring to bbum's post, I read that. I'm assuming that heapshot 
 is now labelled mark generations but otherwise is the same thing. The 
 problem with this in my case is that a generation is a new URL download and 
 that's fired off automatically by either the previous one completing or a 
 timer that's set to a variable time based on the target time of the 
 playlist entry. There's no clear means for me to hit mark generation at 
 exactly the right time. That might not matter all that much in that the 
 process is continuous, so as long as I'm downloading a stream at a fairly 
 steady rate, and hit the button at regular intervals, there should be a 
 reasonable similarity between runs.
 
 Doing that, I get inconclusive results. Most of the memory that is left is 
 like this:
 
 SnapshotTimestampGrowth# Persistent
 Generation B01:32.780.3752.09 MB38
 VM: Performance tool data2.08 MB4
  0x11681600001:13.421.801532.00 KB 
  0x1162ed00001:32.145.259532.00 KB 
  0x1161401:23.051.011532.00 KB 
  0x1161e500001:02.847.030532.00 KB 
 
 
 Which suggests it's memory allocated by Allocations itself.
 
 But where I'm checking this over longer time periods isn't in Instruments at 
 all, but in Xcode's memory viewer. Unfortunately that doesn't give me a 
 breakdown, just an overall usage.
 
 --Graham
 
 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Graham Cox

 On 13 Jan 2015, at 12:21 pm, Roland King r...@rols.org wrote:
 
 Did you read the devforums thread I pointed you at a couple of weeks ago?


Umm, not sure Roland. I read the blog post by bbum about using Allocations, 
which is the one you linked in this thread. Did you mean something else? 
Forgive me, I can't locate the link if so.

If you're referring to bbum's post, I read that. I'm assuming that heapshot 
is now labelled mark generations but otherwise is the same thing. The problem 
with this in my case is that a generation is a new URL download and that's 
fired off automatically by either the previous one completing or a timer that's 
set to a variable time based on the target time of the playlist entry. 
There's no clear means for me to hit mark generation at exactly the right 
time. That might not matter all that much in that the process is continuous, so 
as long as I'm downloading a stream at a fairly steady rate, and hit the button 
at regular intervals, there should be a reasonable similarity between runs.

Doing that, I get inconclusive results. Most of the memory that is left is like 
this:

SnapshotTimestamp   Growth  # Persistent
Generation B01:32.780.375   2.09 MB 38
 VM: Performance tool data  2.08 MB 4
  0x116816000   01:13.421.801   532.00 KB
  0x1162ed000   01:32.145.259   532.00 KB
  0x11614   01:23.051.011   532.00 KB
  0x1161e5000   01:02.847.030   532.00 KB


Which suggests it's memory allocated by Allocations itself.

But where I'm checking this over longer time periods isn't in Instruments at 
all, but in Xcode's memory viewer. Unfortunately that doesn't give me a 
breakdown, just an overall usage.

--Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Graham Cox
Thanks - sorry I missed it in the first mail for some reason.

An interesting thread. This remark from Quinn stood out for me:

If you stop issuing new requests, NSURL{Session,Connection} quickly recovers 
this memory to the point where, at the end of a cycle like this, the memory use 
(as shown by Allocations) is pretty much the same as when you started (a 
generational analysis shows just a few KiB of growth).  So the problem here is 
not a leak, or even abandoned memory, but rather a delay in recovering memory.

This could be what I'm seeing as well, since as a stream is downloaded, each 
chunk is pretty much requested as soon as the previous one completes, and is 
triggered by that completion (though I am rescheduling it on the main thread, 
which in turn adds it to the session's operation queue).

What's not clear is what is needed to cause the memory recovery to occur. I 
presume that invalidating the session will do that, but that isn't appropriate 
for in-between chunks.

I'll look into this angle and see if I can prove anything. If so, I'll file a 
radar and hope it comes back as dupe, fix imminent :) (though I won't be 
holding my breath)

--Graham






 On 13 Jan 2015, at 2:01 pm, Roland King r...@rols.org wrote:
 
 https://devforums.apple.com/message/1056669#1056669
 
 No that one from the same mail. 
 
 
 
 On 13 Jan 2015, at 10:51, Graham Cox graham@bigpond.com wrote:
 
 
 On 13 Jan 2015, at 12:21 pm, Roland King r...@rols.org wrote:
 
 Did you read the devforums thread I pointed you at a couple of weeks ago?
 
 
 Umm, not sure Roland. I read the blog post by bbum about using Allocations, 
 which is the one you linked in this thread. Did you mean something else? 
 Forgive me, I can't locate the link if so.
 
 If you're referring to bbum's post, I read that. I'm assuming that 
 heapshot is now labelled mark generations but otherwise is the same 
 thing. The problem with this in my case is that a generation is a new URL 
 download and that's fired off automatically by either the previous one 
 completing or a timer that's set to a variable time based on the target 
 time of the playlist entry. There's no clear means for me to hit mark 
 generation at exactly the right time. That might not matter all that much 
 in that the process is continuous, so as long as I'm downloading a stream at 
 a fairly steady rate, and hit the button at regular intervals, there should 
 be a reasonable similarity between runs.
 
 Doing that, I get inconclusive results. Most of the memory that is left is 
 like this:
 
 SnapshotTimestampGrowth# Persistent
 Generation B01:32.780.3752.09 MB38
 VM: Performance tool data2.08 MB4
  0x11681600001:13.421.801532.00 KB 
  0x1162ed00001:32.145.259532.00 KB 
  0x1161401:23.051.011532.00 KB 
  0x1161e500001:02.847.030532.00 KB 
 
 
 Which suggests it's memory allocated by Allocations itself.
 
 But where I'm checking this over longer time periods isn't in Instruments at 
 all, but in Xcode's memory viewer. Unfortunately that doesn't give me a 
 breakdown, just an overall usage.
 
 --Graham
 
 


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-12 Thread Roland King

 On 13 Jan 2015, at 11:20, Graham Cox graham@bigpond.com wrote:
 
 Thanks - sorry I missed it in the first mail for some reason.
 
 An interesting thread. This remark from Quinn stood out for me:
 
 If you stop issuing new requests, NSURL{Session,Connection} quickly recovers 
 this memory to the point where, at the end of a cycle like this, the memory 
 use (as shown by Allocations) is pretty much the same as when you started (a 
 generational analysis shows just a few KiB of growth).  So the problem here 
 is not a leak, or even abandoned memory, but rather a delay in recovering 
 memory.
 
 This could be what I'm seeing as well, since as a stream is downloaded, each 
 chunk is pretty much requested as soon as the previous one completes, and is 
 triggered by that completion (though I am rescheduling it on the main thread, 
 which in turn adds it to the session's operation queue).

Yes I saw that in the code you posted way up there in the thread sometime and 
that’s what made me think of that devforums thread which I have no idea why I 
was reading in the first place. But indeed the recollection I had was that the 
poster in that thread was also chaining new requests to the completion of old 
ones and that appeared to be triggering the memory growth behaviour in his app. 

 
 What's not clear is what is needed to cause the memory recovery to occur. I 
 presume that invalidating the session will do that, but that isn't 
 appropriate for in-between chunks.

I think ‘taking a break’ is probably what’s necessary to cause the memory 
recovery to occur. Whether that means delaying 1 second between every request, 
or doing a batch of 50 and then not issuing another request for 1/2 a minute I 
have no idea, but it’s probably pretty simple to put in code which does N 
requests and then waits T seconds before doing the next one then trying some 
values of N and T to see if it does anything at all. 


 
 I'll look into this angle and see if I can prove anything. If so, I'll file a 
 radar and hope it comes back as dupe, fix imminent :) (though I won't be 
 holding my breath)
 

well you might get one of your hopes there :)


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread David Duncan

 On Jan 1, 2015, at 3:38 PM, Graham Cox graham@bigpond.com wrote:
 
 Hi all,
 
 I know I'm very, very late to the party, but I'm building my first ever 
 project with ARC instead of manual retain/release (which I was always very 
 comfortable with). Frankly, I'm finding it frustrating because it seems much 
 harder to know how memory is managed. Anyway. I will plough on - no doubt 
 I'll get used to it.

The first thing to keep in mind is that unless otherwise qualified, all object 
references are owned - locals, ivars, array entries, etc. The places where this 
isn’t possible (such as structs) are flagged as compiler errors. The lifetime 
of ownership can typically be considered as “usage scoped” - that is, the 
object is owned up until its last reference, where by default you can think of 
it as released. There are exceptions to both of these rules, but they are 
generally minor and many likely line up with your expectations as well.

The most prominent exception has to do with inner pointers to things that are 
not Obj-C objects (such as -[UIColor CGColor]) where ARC doesn’t take ownership 
of the returned object (because it isn’t an Obj-C object) and your last 
reference to the outer object (a UIColor in this case) ends before your usage 
of the inner non-object.

But thats just to help you understand/get used to ARC, it doesn’t likely apply 
to your issue at hand :).

 
 I'm using NSURLSession and NSURLSessionDataTask to fetch chunks of data from 
 a .m3u8 playlist. It works pretty well, but I'm seeing a gradual increase in 
 memory usage as my app runs. Under classical memory management, I would 
 probably have little difficulty in isolating the problem, but with ARC I'm 
 finding it much harder to track down because it's unclear when certain 
 objects come to the end of their lives. Anyway, running in Instruments shows 
 a constant list of calls to malloc() from 
 HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, unsigned long) 
 in the CFNetwork library, allocating 132KB. These blocks are allocated at a 
 high rate (over 100x per second) as the app runs, and as far as I can see are 
 never freed. I'm not directly using this API, it must be something internal 
 to NSURLSession.
 
 How can I ensure that these blocks are freed? I'm assuming that a leak in the 
 OS of this sort would have been spotted, so my assumption here is that I'm 
 doing something wrong that prevents proper freeing.

Generally the answer would be to stop referencing objects when you don’t need 
them anymore, but Instruments’s Allocations tool would be the most useful thing 
to use to debug this - in particular retain/release tracking would likely be 
the most useful way to debug this issue. I would suspect the memory blocks at 
hand are being allocated for receiving the downloaded data and possibly wrapped 
as NSData objects.

 
 The way I'm using NSURLSession seems to be normal, as far as I can tell. I 
 have an object that allocates a NSURLSession and this session exists for as 
 long as the task runs, which can be a very long time. Each chunk of data is 
 added to the session as a NSURLSessionDataTask and I supply a completion 
 block. The completion block simply appends the data it receives to a file and 
 fires off some notifications. The completion block may or may not schedule 
 the download of the following chunk, depending on various factors, but it 
 doesn't do anything special to tell the task it has finished - as far as I 
 can tell from documentation, the fact the completion block is called is 
 because the task has finished, so I can just forget about it.
 
 The session itself is invalidated when the owning object is dealloced, but 
 that might be hours or days later when the user decides to discard the task. 
 Otherwise it stays alive indefinitely. I'm wondering if that's the right 
 thing to do? The docs suggest that a NSURLSession is somewhat like a tab in a 
 web browser, so it lives as long as that tab exists.
 
 Any clues as to how I can track down the leak or whether there's an obvious 
 missing step that should free temporary buffers used by NSURLSessionDataTask 
 would be gratefully received at this point.
 
 
 --Graham
 
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/david.duncan%40apple.com
 
 This email sent to david.dun...@apple.com

--
David Duncan


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com


Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Quincey Morris
On Jan 1, 2015, at 17:20 , Graham Cox graham@bigpond.com wrote:
 
 I'm using Allocations, but I'm finding the volume of data a bit overwhelming.
 
 As an aside, Leaks shows nothing at all. Does that mean I'm not actually 
 leaking anything?

Forget Leaks, it’s an utter waste of time*. Use marked generations. The 
persistent increase in each generation is your real “leak”.

— In code where things happen repeatedly in the background, it can be hard to 
get your app into a quiescent state (in terms of allocations) so that you can 
find a good place to mark a new generation in Instruments. You may have 
temporarily add code to create and/or prolong such a quiescent state.

— It’s generally not useful to *start* by looking at the retain/release 
history. You’ll find problem objects easily, but you won’t know where they came 
from or why they didn’t get released.

— In the list of objects incrementally leaked in a generation**, look for the 
ones that you actually created (either objects of your own classes, or objects 
that were obviously created at a particular known place in your code). Out of 
those objects, try to eliminate the ones that appear to be “children” of 
others. 

— Ideally, you’ll find two sorta-kinda top-level objects remain. The 
presumption is then that there’s a reference cycle between them. For example, 
you might find that one is a window controller and the other is something in 
your data model***. Or, you might find that one is a block, and the other is 
whatever created the block.

— Audit the relevant source code. It’s often easiest and quickest to find the 
cycle just by inspecting the declarations/blocks.

— Only if that goes nowhere is it time to start analyzing the retain/release 
history of a generation in Instruments. By now, though, you should have a vague 
idea of what you’re looking for.

— Start by getting Instruments to pair as many retains and releases as it can 
automatically. 

— If that’s unproductive, start over and compare them all yourself. (But I 
should add that I haven’t spent much time doing this in Yosemite yet. The UI 
may be a bit different since Mavericks, and the auto-pairing may work a bit 
differently, too.)


** Create multiple generations, and look not only at what was leaked in each 
generation, but what’s repetitive in the pattern of leaks. Your real culprit 
should produce an identical pattern every time. Leaks unique to a generation 
aren’t what you’re looking for here. (I think this is the debugging equivalent 
of the second derivative.)

*** That usually means a window delegate reference needs to be manually nil’ed 
when the window closes, because we learned how to do bad memory management in 
the bad old days.

 That usually means the block and the ‘self’ it captured mutually refer to 
each other. I’m betting this is what’s wrong in your case.

* I should say, I’m not scorning Leaks. It’s just that experienced Obj-C 
developers tend not to make the kinds of mistakes that Leaks can detect. 
Experienced developers make other, better mistakes.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Graham Cox

 On 2 Jan 2015, at 10:52 am, David Duncan david.dun...@apple.com wrote:
 
 The first thing to keep in mind is that unless otherwise qualified, all 
 object references are owned - locals, ivars, array entries, etc. The places 
 where this isn’t possible (such as structs) are flagged as compiler errors. 
 The lifetime of ownership can typically be considered as “usage scoped” - 
 that is, the object is owned up until its last reference, where by default 
 you can think of it as released. There are exceptions to both of these rules, 
 but they are generally minor and many likely line up with your expectations 
 as well.

Thanks David, that does agree with the way I've been thinking about memory 
management with ARC, so I guess I'm probably not too far wrong. I don't think 
I'm running into any of those corner cases - everything is an NSObject, no CF 
stuff (in my code), and no structs, etc.

 Generally the answer would be to stop referencing objects when you don’t need 
 them anymore, but Instruments’s Allocations tool would be the most useful 
 thing to use to debug this - in particular retain/release tracking would 
 likely be the most useful way to debug this issue. I would suspect the memory 
 blocks at hand are being allocated for receiving the downloaded data and 
 possibly wrapped as NSData objects.

I'm using Allocations, but I'm finding the volume of data a bit overwhelming.

As an aside, Leaks shows nothing at all. Does that mean I'm not actually 
leaking anything?

What I'm seeing sort of agrees with expectations - the memory usage graph has a 
broadly sawtooth waveform as each download task is created, builds up, is 
processed and released. However the underlying memory usage continues to climb, 
with the sawtooth on top. Breaking down the allocations shows that the 132KB 
bufers are the vast majority of the allocations, but maybe my interpretation 
that they're not being freed is wrong - they are listed but maybe that doesn't 
mean they're not being freed? I don't know - there's the problem, I'm not 
terribly clear on how to interpret the data.

Regarding the NSData I'm passed in my NSURLSessionDataTask completion block 
(which are the biggest blocks I handle), I write that data to an open file 
handle and that's the last time I reference it. I don't own that NSData anyway, 
so even under classic MM I wouldn't do anything special about it. I guess 
NSFileHandle could be retaining that NSData. I leave that file handle open 
continually as long as a download stream is available, so it might be that it's 
not releasing NSData blocks passed to -writeData: until it is closed. That 
could explain what I'm seeing, though thinking about *why* NSFileHandle would 
retain that data is not so obvious - why indeed? Wouldn't it just copy that 
data to the file and release it?

--Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Cosmo
A while back I had a similar sounding issue in an iOS project I was working on. 
The memory usage kept growing, although I could find no obvious culprits in my 
code after hours of exploration. My solution probably doesn’t pertain to you, 
but I thought I’d pass it along just in case it’s something you might have 
overlooked. 

I showed my project to another more experienced developer seeking help. He 
agreed with my assessment that there weren’t any apparent major problems with 
my code. But he discovered that I had left Zombies detection turned on in the 
project scheme settings (left on from exploring another issue some time back). 
So of course Instruments was showing me the memory that Zombies was holding 
onto. Turning off Zombies detection gave me a very steady memory usage pattern.

 On Jan 1, 2015, at 5:20 PM, Graham Cox graham@bigpond.com wrote:
 
 I'm using Allocations, but I'm finding the volume of data a bit overwhelming.
 
 As an aside, Leaks shows nothing at all. Does that mean I'm not actually 
 leaking anything?
 
 What I'm seeing sort of agrees with expectations - the memory usage graph has 
 a broadly sawtooth waveform as each download task is created, builds up, is 
 processed and released. However the underlying memory usage continues to 
 climb, with the sawtooth on top. Breaking down the allocations shows that the 
 132KB bufers are the vast majority of the allocations, but maybe my 
 interpretation that they're not being freed is wrong - they are listed but 
 maybe that doesn't mean they're not being freed? I don't know - there's the 
 problem, I'm not terribly clear on how to interpret the data.
 
 Regarding the NSData I'm passed in my NSURLSessionDataTask completion block 
 (which are the biggest blocks I handle), I write that data to an open file 
 handle and that's the last time I reference it. I don't own that NSData 
 anyway, so even under classic MM I wouldn't do anything special about it. I 
 guess NSFileHandle could be retaining that NSData. I leave that file handle 
 open continually as long as a download stream is available, so it might be 
 that it's not releasing NSData blocks passed to -writeData: until it is 
 closed. That could explain what I'm seeing, though thinking about *why* 
 NSFileHandle would retain that data is not so obvious - why indeed? Wouldn't 
 it just copy that data to the file and release it?


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Joar Wingfors

 On 1 jan 2015, at 18:26, Graham Cox graham@bigpond.com wrote:
 
 
 On 2 Jan 2015, at 12:48 pm, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
  That usually means the block and the ‘self’ it captured mutually refer 
 to each other. I’m betting this is what’s wrong in your case.
 
 
 
 
 Quincey, thanks for your lengthy and well-thought-out reply (as usual) :)
 
 I think you've hit the nail straight on the head (as usual), with the 
 block/self problem. It's one I knew about before, but had forgotten again in 
 my excitement at getting the code running. The question is what to do about 
 it.
 
 My handler block refers to 'self' quite extensively - it calls other methods 
 of self and also refers to properties such as self.delegate. I'm not quite 
 sure how I can rework it not to refer to self. Maybe I just need to not use 
 the completion block approach and use a delegate callback instead. I need to 
 go away and think about this... thanks for the slap about the head.


You can always employ the weakself+strongself pattern:

__weak Foo *weakSelf = self;
AsyncBar(^{
Foo *strongSelf = weakSelf;
if (nil != strongSelf) {
[strongSelf doStuff];
// more stuff
}
});

That said, if an object is going away it's typically better to use explicit 
cleanup / teardown, than relying on __weak. Tear down bindings, KVO, timers, 
delayed runloop invocations, outstanding async work, etc. More direct, more 
predictable, easier to troubleshoot/debug. 

Joar


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Joar Wingfors

 On 1 jan 2015, at 18:22, Roland King r...@rols.org wrote:
 
 +1 for all of this. I wouldn't call leaks an utter waste of time, but it 
 really does only find pure retain cycles (which it then annotates very 
 nicely) and not memory which is really is pinned by a real reference which is 
 more often the case. Also, if you're using KVO anywhere, this tends to 
 entirely defeat leaks even though KVO isn't a strong reference and shouldn't 
 be treated like one, it is. That makes leaks less useful than it could be for 
 me because I'm always KVO'ing something.   


I don't think leaks would find cycles. I could be wrong, but I don't think it's 
sophisticated enough to perform that additional level of analysis. I think it 
only finds stuff that's truly referenced from nowhere else on the heap. 


 There's an old blog by bbum which covered using generational analysis for 
 finding leaks which aren't leaks. Xcode has changed quite a lot since then 
 but some of the screens look quite similar even now. I routinely put my code 
 through this torture test, it's so easy to run and the results are often very 
 illuminating. 
 
 http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/


That functionality has since been integrated into Instruments, so it's easier 
to use. 

Joar



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Roland King

 On 2 Jan 2015, at 10:52, Joar Wingfors j...@joar.com wrote:
 
 
 On 1 jan 2015, at 18:22, Roland King r...@rols.org wrote:
 
 +1 for all of this. I wouldn't call leaks an utter waste of time, but it 
 really does only find pure retain cycles (which it then annotates very 
 nicely) and not memory which is really is pinned by a real reference which 
 is more often the case. Also, if you're using KVO anywhere, this tends to 
 entirely defeat leaks even though KVO isn't a strong reference and shouldn't 
 be treated like one, it is. That makes leaks less useful than it could be 
 for me because I'm always KVO'ing something.   
 
 
 I don't think leaks would find cycles. I could be wrong, but I don't think 
 it's sophisticated enough to perform that additional level of analysis. I 
 think it only finds stuff that's truly referenced from nowhere else on the 
 heap. 
 

Perhaps we're talking cross purposes because it definitely finds what I'm 
calling cycles, where object A references B strongly and B references A 
strongly (or a longer chain of objects which eventually forms an equivalent 
loop). If that loop of objects isn't strongly referenced by anything else and 
is thus 'leaked', leaks not only finds it but gives you a pretty diagram 
showing how all the objects are strongly referencing each other, with property 
names etc. 

IIRC that facility arrived the same year as ARC. It's occasionally useful. 



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Clark S. Cox III

 On Jan 1, 2015, at 18:26, Graham Cox graham@bigpond.com wrote:
 
 
 On 2 Jan 2015, at 12:48 pm, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
  That usually means the block and the ‘self’ it captured mutually refer 
 to each other. I’m betting this is what’s wrong in your case.
 
 
 
 
 Quincey, thanks for your lengthy and well-thought-out reply (as usual) :)
 
 I think you've hit the nail straight on the head (as usual), with the 
 block/self problem. It's one I knew about before, but had forgotten again in 
 my excitement at getting the code running. The question is what to do about 
 it.
 
 My handler block refers to 'self' quite extensively - it calls other methods 
 of self and also refers to properties such as self.delegate. I'm not quite 
 sure how I can rework it not to refer to self. Maybe I just need to not use 
 the completion block approach and use a delegate callback instead. I need to 
 go away and think about this... thanks for the slap about the head.
 
 —Graham

One of the first things I define in any ARC codebase I’m going to be working on 
is:

#define DECLARE_WEAK_SELF  __weak __typeof__(self) weak_self = self;
#define DECLARE_STRONG_SELF__strong __typeof__(weak_self) self = weak_self;

And I use it like so:

- (void)method {
DECLARE_WEAK_SELF

self.someBlock = ^{
DECLARE_STRONG_SELF;
//Use “self” as usual here
};

self.someOtherBlock = ^{
DECLARE_STRONG_SELF;
//Use “self” as usual here
};
}

-- 
Clark Smith Cox III
clarkc...@gmail.com



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Roland King

 
 My handler block refers to 'self' quite extensively - it calls other methods 
 of self and also refers to properties such as self.delegate. I'm not quite 
 sure how I can rework it not to refer to self. Maybe I just need to not use 
 the completion block approach and use a delegate callback instead. I need to 
 go away and think about this... thanks for the slap about the head.
 
 --Graham
 
 

Having a handler block which refers to self is not in and of itself a problem, 
very many blocks implicitly do. The block retains self, however in most cases 
something else retains the block and the self reference goes away when the 
block is released. The problem usually comes when the handler block which 
refers to self is also a property of the object, eg myObj.completion = ^{ .. 
block referring to myobj }. Xcode normally warns you if you even get close to 
doing that however. 

If that's happening then allocations should show you are amassing whatever 
objects those are and never releasing them, does it? Or you can be old skool 
about it and NSLog() dealloc() to see if it's getting called.

Two ways around block retain cycles are 

1) If the block is a property of the object, eg a callback block, when you've 
called the block, nil the property, break the cycle. 
2) The strong/weak dance. You make a weak pointer to self which is actually 
captured in the block, then in the block you assign it to a strong pointer, 
then check for nil, then use that pointer. 

MyObj __weak *weakSelf = self;

^{ 
MyObj *strongSelf = weakSelf;
if( strongSelf )
{
// do work using strongSelf explicitly
}
}



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Graham Cox

 On 2 Jan 2015, at 12:48 pm, Quincey Morris 
 quinceymor...@rivergatesoftware.com wrote:
 
  That usually means the block and the ‘self’ it captured mutually refer 
 to each other. I’m betting this is what’s wrong in your case.
 
 


Quincey, thanks for your lengthy and well-thought-out reply (as usual) :)

I think you've hit the nail straight on the head (as usual), with the 
block/self problem. It's one I knew about before, but had forgotten again in my 
excitement at getting the code running. The question is what to do about it.

My handler block refers to 'self' quite extensively - it calls other methods of 
self and also refers to properties such as self.delegate. I'm not quite sure 
how I can rework it not to refer to self. Maybe I just need to not use the 
completion block approach and use a delegate callback instead. I need to go 
away and think about this... thanks for the slap about the head.

--Graham





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Roland King
+1 for all of this. I wouldn't call leaks an utter waste of time, but it really 
does only find pure retain cycles (which it then annotates very nicely) and not 
memory which is really is pinned by a real reference which is more often the 
case. Also, if you're using KVO anywhere, this tends to entirely defeat leaks 
even though KVO isn't a strong reference and shouldn't be treated like one, it 
is. That makes leaks less useful than it could be for me because I'm always 
KVO'ing something.   

There's an old blog by bbum which covered using generational analysis for 
finding leaks which aren't leaks. Xcode has changed quite a lot since then but 
some of the screens look quite similar even now. I routinely put my code 
through this torture test, it's so easy to run and the results are often very 
illuminating. 

http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/
 
http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/

I do remember there was a recent discussion on the dev forums about 
NSURLConnection 'leaking' in iOS8. It appears it wasn't actually leaking, but 
it did amass memory which it gave up in a delayed manner only when you stopped 
making requests. Again that's iOS, but I do wonder if the same code is in OSX 
and whether the same effect is there too. That discussion, which doesn't quite 
reach a conclusion, is here .. 
https://devforums.apple.com/message/1056669#1056669 
https://devforums.apple.com/message/1056669#1056669


 On 2 Jan 2015, at 09:48, Quincey Morris quinceymor...@rivergatesoftware.com 
 wrote:
 
 On Jan 1, 2015, at 17:20 , Graham Cox graham@bigpond.com wrote:
 
 I'm using Allocations, but I'm finding the volume of data a bit overwhelming.
 
 As an aside, Leaks shows nothing at all. Does that mean I'm not actually 
 leaking anything?
 
 Forget Leaks, it’s an utter waste of time*. Use marked generations. The 
 persistent increase in each generation is your real “leak”.
 
 — In code where things happen repeatedly in the background, it can be hard to 
 get your app into a quiescent state (in terms of allocations) so that you can 
 find a good place to mark a new generation in Instruments. You may have 
 temporarily add code to create and/or prolong such a quiescent state.
 
 — It’s generally not useful to *start* by looking at the retain/release 
 history. You’ll find problem objects easily, but you won’t know where they 
 came from or why they didn’t get released.
 
 — In the list of objects incrementally leaked in a generation**, look for the 
 ones that you actually created (either objects of your own classes, or 
 objects that were obviously created at a particular known place in your 
 code). Out of those objects, try to eliminate the ones that appear to be 
 “children” of others. 
 
 — Ideally, you’ll find two sorta-kinda top-level objects remain. The 
 presumption is then that there’s a reference cycle between them. For example, 
 you might find that one is a window controller and the other is something in 
 your data model***. Or, you might find that one is a block, and the other is 
 whatever created the block.
 
 — Audit the relevant source code. It’s often easiest and quickest to find the 
 cycle just by inspecting the declarations/blocks.
 
 — Only if that goes nowhere is it time to start analyzing the retain/release 
 history of a generation in Instruments. By now, though, you should have a 
 vague idea of what you’re looking for.
 
 — Start by getting Instruments to pair as many retains and releases as it can 
 automatically. 
 
 — If that’s unproductive, start over and compare them all yourself. (But I 
 should add that I haven’t spent much time doing this in Yosemite yet. The UI 
 may be a bit different since Mavericks, and the auto-pairing may work a bit 
 differently, too.)
 
 
 ** Create multiple generations, and look not only at what was leaked in each 
 generation, but what’s repetitive in the pattern of leaks. Your real culprit 
 should produce an identical pattern every time. Leaks unique to a generation 
 aren’t what you’re looking for here. (I think this is the debugging 
 equivalent of the second derivative.)
 
 *** That usually means a window delegate reference needs to be manually 
 nil’ed when the window closes, because we learned how to do bad memory 
 management in the bad old days.
 
  That usually means the block and the ‘self’ it captured mutually refer 
 to each other. I’m betting this is what’s wrong in your case.
 
 * I should say, I’m not scorning Leaks. It’s just that experienced Obj-C 
 developers tend not to make the kinds of mistakes that Leaks can detect. 
 Experienced developers make other, better mistakes.
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 

Re: Debugging memory leak in NSURLSession with ARC

2015-01-01 Thread Graham Cox

 On 2 Jan 2015, at 1:46 pm, Roland King r...@rols.org wrote:
 
 Having a handler block which refers to self is not in and of itself a 
 problem, very many blocks implicitly do. The block retains self, however in 
 most cases something else retains the block and the self reference goes away 
 when the block is released. The problem usually comes when the handler block 
 which refers to self is also a property of the object, eg myObj.completion = 
 ^{ .. block referring to myobj }. Xcode normally warns you if you even get 
 close to doing that however. 

Right. Well, my block refers to self, but it's not a property of self. Quickly 
trying it with a weak version of self shows no change of behaviour regarding 
memory usage, so I guess that was a red herring.

Just to be sure, I have:

my 
object...[owns]...NSURLSession...[owns]...NSURLSessionDataTask...[owns]...completion
 block...[refers to]...my object

I don't think this amounts to a retain cycle, because when the session has 
finished the task, it will release it, and its block, and those references to 
self (my object) that it has.


 
 If that's happening then allocations should show you are amassing whatever 
 objects those are and never releasing them, does it? Or you can be old skool 
 about it and NSLog() dealloc() to see if it's getting called.


What appears to be amassing are 132KB malloc'd blocks (by the hundreds). These 
are created by HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, 
unsigned long), down in CFNetwork. The stack trace is:

   0 libsystem_malloc.dylib malloc_zone_malloc
   1 libsystem_malloc.dylib malloc
   2 CFNetwork HTTPNetStreamInfo::_readStreamClientCallBack(__CFReadStream*, 
unsigned long)
   3 CFNetwork 
CFNetworkReadStream::_readStreamClientCallBackCallBack(__CFReadStream*, 
unsigned long, void*)
   4 CoreFoundation _signalEventSync
   5 CoreFoundation _cfstream_shared_signalEventSync
   6 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
   7 CoreFoundation __CFRunLoopDoSources0
   8 CoreFoundation __CFRunLoopRun
   9 CoreFoundation CFRunLoopRunSpecific
  10 CFNetwork +[NSURLConnection(Loader) _resourceLoadLoop:]
  11 Foundation __NSThread__main__
  12 libsystem_pthread.dylib _pthread_body
  13 libsystem_pthread.dylib _pthread_start
  14 libsystem_pthread.dylib thread_start


Which actually doesn't directly link it to anything in my code, though I think 
it's safe to say it's something set up by NSURLSession or NSURLSessionDataTask, 
which I do create in my code.

BUT, and this is a big but, I'm not sure if I'm interpreting Allocations 
correctly. I have it set to created and persistent, and graphing these blocks 
shows a very close corrlation between them and the overall memory usage 
profile, so my interpretation is that these are predominantly responsible for 
the memory usage of my app. However, the shape of the graph does show that a 
lot of these blocks are freed, but not all, leading to the gradual increase in 
baseline allocation.

Here's the rough outline of the code I'm using to run the 
NSURLSessionDataTasks. This is a method of my object, and it is called once 
when there is data to begin downloading, and runs itself as long as there are 
items in the queue to be processed.

- (BOOL)dequeueNextChunk
{
// removes next URL from the chunks queue and starts it asynchronously 
downloading as a session. Returns YES if a chunk was dequeued, NO if not (queue 
empty).

XVMediaChunk* chunk = [queuedChunkURLs firstObject];

if( chunk )
{
// dequeue

[queuedChunkURLs removeObjectAtIndex:0];

// schedule download and start it

[[self.session dataTaskWithURL:chunk.url 
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSHTTPURLResponse* httpResponse = 
(NSHTTPURLResponse*)response;

if( httpResponse.statusCode == 200 )
{
// got a valid response. If it's a valid chunk 
add the data to the chunk object and pass it along to the next step.

if([httpResponse.MIMEType 
isEqualToString:@video/mp2t])
{
chunk.data = data;

[self processVideoChunk:chunk];

// and schedule the next chunk in the 
queue

[self 
performSelectorOnMainThread:@selector(dequeueNextChunk) withObject:nil 
waitUntilDone:NO];
}
}
else