Swift - Risk in using autoreleasepool? CPU usage? - swift

With the Xcode Profiler I have just spotted a not really necessary memory peak on JSON decoding. Apparently it's a known issue and I should wrap the call in an autoreleasepool which helped:
//extension..
var jsonData: Data? {
return autoreleasepool{ try? JSONSerialization.data(withJSONObject: self, options: []) }
}
I found another few big chunks of allocations that were not really needed so I applied my newly-learned trick to other code as well, such as the following:
var protoArray = [Proto_Bit]()
for bit in data {
autoreleasepool{
if let str = bit.toJSONString() {
if let proto = try? Proto_Bit(jsonString: str) {
protoArray.append(proto)
}
}
}
}
Now, before I wrap every single instruction of my code (or at least wherever I see fit) in this autoreleasepool thing, I would like to ask if there are any risks or drawbacks associated to it.
With these two wraps I was able to reduce my peak memory consumption from 500mb to 170mb. I am aware that Swift also does these kinds of things behind the scenes and probably has some guards in place however I would rather be safe than sorry.
does autoreleasepool come with a CPU overhead? If it is 5% I would be okay with that since it sounds like a good tradeoff, if it's more I would have to investigate
can I mess up anything using autoreleasepool? Null pointers, thread locking etc. since the block structure looks a bit scary.. or is this just telling the hardware "at the end of the bracket clean up and close the door behind you" without affecting other objects?

Autorelease Pools are a mechanism which comes from Objective-C for helping automate memory management and ensure that objects and resources are released "eventually", where that "eventually" comes when the pool is drained. i.e., an autorelease pool, once created on a thread, captures (retains) all objects which are -autoreleaseed while the pool is active — when the pool is drained, all of those objects are released. (Note that this is a Foundation feature in conjunction with the Objective-C runtime, and is not directly integrated with hardware: it's way, way higher-level than that.)
As a short-hand for managing autorelease pools directly (and avoiding creating NSAutoreleasePool instances directly), Objective-C introduced the #autoreleasepool language keyword, which effectively creates an autorelease pool at the beginning of the scope, and drains it at the end:
#autoreleasepool /* create an autorelease pool to capture autoreleased objects */ {
// ... do stuff ...
} /* release the autoreleasepool, and all objects that were in it */
Introducing autorelease pools manually in this way grants you more control over when autoreleased objects are effectively cleaned up: if you know that a block of code creates many autoreleased objects that really don't need to outlive that block of code, that may be a good candidate for wrapping up in an #autoreleasepool.
Autorelease pools pre-date ARC, which automates reference counting in a deterministic way, and its introduction made autorelease pools became largely unnecessary in most code: if an object can be deterministically retained and released, there's no need to rely on autoreleasing it "at some point". (And in fact, along with regular memory management calls like -retain and -release themselves, ARC will not allow you to call -autorelease on objects directly either.)
Swift, following the ARC memory management model, also does not rely on autoreleasing objects — all objects are deterministically released after their last usage. However: Swift does still need to interoperate with Objective-C code, and notable, not all Objective-C code (including a lot of code in, e.g., Foundation) uses ARC. Many internal Apple frameworks still use Objective-C's manual memory management, and thus still rely on autoreleased objects.
On platforms where Swift might need to interoperate with Objective-C code, no work needs to be explicitly done in order to allow autoreleased objects to eventually be released: every Swift application on Darwin platforms has at least one implicit autorelease pool at the root of the process which captures autoreleased objects. However, as you note: this "eventual" release of Objective-C objects might keep memory usage high until the pool is drained. To help alleviate that high memory usage, Swift has autoreleasepool { ... } (matching Objective-C's #autoreleasepool { ... }), which allows you to explicitly and eagerly capture those autoreleased objects, and free them at the end of the scope.
To answer your questions directly, but in reverse order:
Can I mess up anything using autoreleasepool? For correctly-written code, no. All you're doing is helping the Objective-C runtime clean up these objects a little bit earlier than it would otherwise. And it's critical to note: the objects will only be released by the pool — if their retain count is still positive after the pool releases them, they must still be in use somewhere, and will not be deallocated until that other owner holding on to the object also releases them.
Is it possible that the introduction of an autoreleasepool will cause some unexpected behavior to occur which didn't before? Absolutely. Incorrectly-written code could have accidentally worked due to the fact that an object was incidentally kept alive long enough to prevent unintentional behavior from occurring — and releasing the object sooner might trigger it. But, this is both unlikely (given the miniscule amount of actually manual memory management outside of Apple frameworks) and not something you can rely on: if the code misbehaves inside of a newly-introduced autoreleasepool, it wasn't correct to begin with, and could have backfired on you some other way.
Does autoreleasepool come with a CPU overhead? Yes, and it is likely vanishingly small compared to the actual work an application performs. But, that doesn't mean that sprinkling autoreleasepool all over the place will be useful:
Given the decreasing amount of autoreleased objects in a Swift project as increasing amounts of code transition away from Objective-C, it's becoming rarer to see large numbers of autoreleased objects which need to be eagerly cleaned up. You could sprinkle autoreleasepools everywhere, but it's entirely possible that those pools will be entirely empty, with nothing to clean up
autoreleasepools don't affect native Swift allocations: only Objective-C objects can be autoreleased, which means that for a good portion of Swift code, autoreleasepools are entirely wasted
So, when should you use autoreleasepools?
When you're working with code coming from Objective-C, which
You've measured to show that is contributing to high memory usage thanks to autoreleased objects, which
You've also measured are cleaned up appropriately by the introduction of an autoreleasepool
In other words, exactly what you've done here in your question. So, kudos.
However, try to avoid cargo-culting the insertion of autoreleasepools all over the place: it's highly unlikely to be effective without actual measurements and understanding what might be going on.
[An aside: how do you know when objects/code might be coming from Objective-C? You can't, very easily. A good rule of thumb is that many Apple frameworks are still written in Objective-C under the hood, or may at some layer return an Objective-C object bridged (or not) to Swift — so they may be a likely culprit to investigate if you've measured something actionable. 3rd-party libraries are also much less likely to contain Objective-C these days, but you may also have source access to them to confirm.]
Another note about optimizations and autoreleasepools: in general, you should not typically expect a Release configuration of a build to behave differently with regard to autoreleased objects as opposed to a Debug configuration.
Unlike ARC code (both in Swift and in Objective-C), where the compiler can insert memory management optimizations for code at compile time, autorelease pools are a runtime feature, and since any retain will necessarily keep an object instance alive, even a single insertion of an object into an autorelease pool will keep it alive until it is disposed of at runtime. So, even if the compiler can aggressively optimize the specific locations of retains and releases for most objects in a Release configurations, there's nothing to be done for an object that's autoreleased.
(Well, the ARC optimizer can do some amount of optimization around autoreleasing objects if it has enough visibility into all of the code using the object, the context of the autorelease pools it belongs to, etc., but this is usually very limited because the scope in which the object was originally -autoreleased is usually far from the scope in which the autorelease pool lives, by definition [otherwise it would be a candidate for regular memory management].)

Related

How can I manually zero out memory?

Is it possible to manually clear out the contents of an object from memory?
In particular, I'm dealing with NSData. I've tried using data.length = 0 and data.setData(NSData).
I know ARC will come in and clean up after it is out of scope to whom it belongs, but is it possible to manually force this process when I want?
I think you have some misconceptions about ARC I'd like to clear up. The goal of ARC is is to ensure memory leaks don't occur. It's responsible for tracking the object over its life cycle, and ensuring it's "freed" when no references remain to it.
It's important to note that the memory being "freed" does not imply "writing over it all with 0s".
It simply means that memory will be designated as unused. The freed memory becomes a candidate for allocation when the system needs to allocate memory to new objects.
There's no guarentee, however, that this reallocation will happen, thus it's very possible for your freed memory to contain your original data, and never be overwritten.

Retain count of the start from 4 [duplicate]

I would like to know in what situation did you use -retainCount so far, and eventually the problems that can happen using it.
Thanks.
You should never use -retainCount, because it never tells you anything useful. The implementation of the Foundation and AppKit/UIKit frameworks is opaque; you don't know what's being retained, why it's being retained, who's retaining it, when it was retained, and so on.
For example:
You'd think that [NSNumber numberWithInt:1] would have a retainCount of 1. It doesn't. It's 2.
You'd think that #"Foo" would have a retainCount of 1. It doesn't. It's 1152921504606846975.
You'd think that [NSString stringWithString:#"Foo"] would have a retainCount of 1. It doesn't. Again, it's 1152921504606846975.
Basically, since anything can retain an object (and therefore alter its retainCount), and since you don't have the source to most of the code that runs an application, an object's retainCount is meaningless.
If you're trying to track down why an object isn't getting deallocated, use the Leaks tool in Instruments. If you're trying to track down why an object was deallocated too soon, use the Zombies tool in Instruments.
But don't use -retainCount. It's a truly worthless method.
edit
Please everyone go to http://bugreport.apple.com and request that -retainCount be deprecated. The more people that ask for it, the better.
edit #2
As an update,[NSNumber numberWithInt:1] now has a retainCount of 9223372036854775807. If your code was expecting it to be 2, your code has now broken.
NEVER!
Seriously. Just don't do it.
Just follow the Memory Management Guidelines and only release what you alloc, new or copy (or anything you called retain upon originally).
#bbum said it best here on SO, and in even more detail on his blog.
Autoreleased objects are one case where checking -retainCount is uninformative and potentially misleading. The retain count tells you nothing about how many times -autorelease has been called on an object and therefore how many time it will be released when the current autorelease pool drains.
I do find retainCounts very useful when checked using 'Instruments'.
Using the 'allocations' tool, make sure 'Record reference counts' is turned on and you can go into any object and see its retainCount history.
By pairing allocs and releases you can get a good picture of what is going on and often solve those difficult cases where something is not being released.
This has never let me down - including finding bugs in early beta releases of iOS.
Take a look at the Apple documentation on NSObject, it pretty much covers your question:
NSObject retainCount
In short, retainCount is probably useless to you unless you've implemented your own reference counting system (and I can almost guarantee you won't have).
In Apple's own words, retainCount is "typically of no value in debugging memory management issues".
Of course you should never use the retainCount method in your code, since the meaning of its value depends on how many autoreleases have been applied to the object and that is something you cannot predict. However it is very useful for debugging -- especially when you are hunting down memory leaks in code that calls methods of Appkit objects outside of the main event loop -- and it should not be deprecated.
In your effort to make your point you seriously overstated the inscrutable nature of the value. It is true that it is not always a reference count. There are some special values that are used for flags, for example to indicate that an object should never be deallocated. A number like 1152921504606846975 looks very mysterious until you write it in hex and get 0xfffffffffffffff. And 9223372036854775807 is 0x7fffffffffffffff in hex. And it really is not so surprising that someone would choose to use values like these as flags, given that it would take almost 3000 years to get a retainCount as high as the larger number, assuming you incremented the retainCount 100,000,000 times per second.
What problems can you get from using it? All it does is return the retain count of the object. I have never called it and can't think of any reason that I would. I have overridden it in singletons to make sure they aren't deallocated though.
You should not be worrying about memory leaking until your app is up and running and doing something useful.
Once it is, fire up Instruments and use the app and see if memory leaks really happen. In most cases you created an object yourself (thus you own it) and forgot to release it after you were done.
Don't try and optimize your code as you are writing it, your guesses as to what may leak memory or take too long are often wrong when you actually use the app normally.
Do try and write correct code e.g. if you create an object using alloc and such, then make sure you release it properly.
Never use the -retainCount in your code. However if you use, you will never see it returns zero. Think about why. :-)
You should never use it in your code, but it could definitely help when debugging
The examples used in Dave's post are NSNumber and NSStrings...so, if you use some other classes, such as UIViews, I'm sure you will get the correct answer(The retain count depends on the implementation, and it's predictable).

automatic C++ memory/object instance management? smart pointers?

I would like to have automatic memory disposal in my C++ project.
I don't mind to have some additional conventions in order to obtain this automatic memory disposal - to be specific, I don't mind to have some special coding on creating new object instances (but of course, not anything more as it defeats the purpose).
After some readings on many useful discussions in stackoverflow, I found out that "smart pointers" are referred to the most (along with some reference of third-party c++ garbage collectors).
With only some "textbook" C++ knowledge equipped, I believe that the C++ GCs' complexities make them doesn't worth to be used, in my case.
On the other hand, I have a .NET/Java background, and would like to leverage this experience on C++ too. I'm accustomed to creating object instances and pass them to other classes/functions (I believe it is some bread-and-butter stuff in C++ too).
So, is smart pointers/shared_ptr/boost what I am looking for?
(note that for memory acquiring I mean doing a MyClass* var = new MyClass(), not malloc().)
Some specific background:
Actually what I exactly am trying to do is to write some library functions which can be used in both C++ projects and iPhone projects (note that these are some purely logical business classes, so there should be no portability issues). Although I believe it is not an area that requires high performance (non-game app of iPhone), I have some concerns on resource usage.
Is there any issue in making use of smart pointers in this situation? Are there any better alternatives?
Consider reference counting? Create a base class that keeps a count of how often it is referenced, and deletes itself when that reference count falls to zero.
class RefCounter
{
public:
RefCounter() : mRefCount(1) { }
virtual ~RefCounter() { }
void retain() { mRefCounter++; }
void release() {
if(mRefCount) mRefCount--;
if(!mRefCount) delete this;
}
protected:
unsigned int mRefCounter;
};
Any referring object that needs the instance would call it's retain() function, and when done, it would call release(). The last object to call release would cause the instance to delete itself. You have to be careful to balance the retains and releases, but this technique is essentially how GC works except that GC implementations hide this reference counting from you.
I learned C++ before automatic GC became all the rage and I've never really warmed to the concept, feeling much more secure knowing exactly when and where each byte of memory was allocated and freed. But that's just me.

Memory management dilemma, Objective -C

I have been testing different features of Objective -C and reached topic which deals with memory management. Apparently upon reading few documents it seems memory management is a very strict in order to build well functioned application.
Now as per my understanding, When we allocate a memory an object's retainCount will become 1. However Something I wrote for learning purposes and it is giving me abnormal retainCount
It might be abnormal number for me, But people who's knows under the hood, Could you please explain how did I get this retainCount and what will be the best way to release it.
Code which has abnormal retainCount,
Object name is : ...(UISlider *) greenSender...
-(IBAction) changeGreen:(UISlider *)greenSender{
showHere.textColor = [UIColor colorWithRed:red.value green:greenSender.value blue:blue.value alpha:1.0];
NSLog(#"retainCount %d",[greenSender retainCount]);
}
Has reatainCount, just after executing my code.
A short explanation will give me a hint, And external reading resources would be appreciated.
Thanks
Do not rely on retain counts. They should only be used as a debugging tool. The reason is that if an object gets retained and autoreleased, its effective retain count has not changed, but its actual retain count has increased by one. It will be released at some point in the future when the autorelease pool drains. Therefore, you cannot rely on the retain count for knowing whether the object has been managed properly or not.
A large retain count such as 8 may indicate a programming bug (such as retaining it too many times), but it could also just be a sign that it has been retained and autoreleased a large number of times, which, although curious, could be perfectly valid.
Do not trust/rely on retainCount. Really.
From Apple:
Important: This method is typically of no value in debugging
memory management issues. Because any number of framework objects may
have retained an object in order to hold references to it, while at
the same time autorelease pools may be holding any number of deferred
releases on an object, it is very unlikely that you can get useful
information from this method.

Asking if an object is invalid

I am trying to determine if an object is valid. The program has (at least) two threads and one of the threads might invalidate the object by removing it from an NSMutableArray. I need the other thread to check either its existence or validity before acting on it.
You can't. The only way to check if the memory your object pointer has still represents a valid object is to dereference it, but dereferencing an "invalid" object (by which I assume you mean one that has been dealloced) will result in either accessing the memory of a new object that has been allocated in the same location, garbage data that may or may not be identical to a normal object, or an unmapped memory page that will result in an immediate EXEC_BAD_ACCESS.
Any time you are holding a reference to an object you might use in the future you must retain it. If you don't you have not shown any interest or ownership in the object and the system may throw it away at any time.
Using objective C accessors and properties instead of directly setting ivars and using retain/release simplifies doing the right thing quite a bit.
Multi-threaded programming is hard. Hard does not begin to capture how difficult it is. This is the kind of hard in which a general, useable, 'reasonably qualified' way of deterministically adding two different numbers together that are being mutated and shared by multiple threads in bounded time without the use of any special assistance from the CPU in the form of atomic instructions would be a major breakthrough and the thesis of your PhD. A deity of your choice would publicly thank you for your contribution to humanity. Just for adding two numbers together. Actually, multi-threaded programming is even harder than that.
Take a look at: Technical Note TN2059
Using collection classes safely with multithreaded applications. It covers this topic in general, and outlines some of the non-obvious pitfalls that await you.
You say
I need the other thread to check either its existence or validity before acting on it.
The easiest way is to hold on to the index of the object in the NSMutableArray and then do the following
if( myObject == [myArray objectAtIndex: myObjectIndex] ) {
// everything is good !
}
else {
// my object is not what I think it is anymore
}
There are clear problem with this approach however
insertion, and deletion will stuff you up
The approach is not thread safe since the array can be changed while you are reading it
I really recomend using a different way to share this array between the two threads. Does it have to be mutable? If it doesn't then make it immutable and then you no longer have to worry about the threading issues.
If it does, then you really have to reconsider your approach. Hopefully someone can give an cocoa way of doing this in a thread safe way as I don't have the experience.