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].)
I am looking at the documentation of IOBufferMemoryDescriptor. It says "... Except where noted, you are also responsible for releasing buffers that you allocate.".
IOBufferMemoryDescriptor::free also exists. My questions is: should I use free or release (or maybe both) to do the cleanup?
free() is called automatically when the last handle is dropped using OSSafeReleaseNULL. (This calls release() internally, but it's usually best to use the macro.)
So, never call the free() method directly, you only need to care about it in the context of overriding it in your own subclasses. Always use the reference counting mechanism on OSObject-derived classes.
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.
I got a memory leak when I detect with instrument. I don`t have so much experience about memory-management, so I can not figure out what is the possible cause for this problem, the memory leak is as below:
I want to know the possible reason about this kind of memory leak. Is some one who can give me some clues?
strdup uses malloc internally, so anything that has been strdup-ed has to be freed using free.
For example:
char *duplicate = strdup("abcdef");
...
free(duplicate);
strdup() is a library function, so you need to go back up the backtrace until you find a caller that's in your code. There you'll find a library call which is resulting in memory being allocated - it should have a corresponding freeing call elsewhere in your program.
(The freeing function is not necessarily a direct call to free() - for example if you call the getaddrinfo() library function the corresponding freeing function is freeaddrinfo()).
I am not sure if the memory address of an object keeps beeing the same over its lifetime. Does it? Or does it change sometimes during the object's existence?
Yes, the address of any given object is constant in Objective-C. This is rather important since objects are always referred to by address. :-) (Garbage collectors which move things about and update all pointers to them exist, but garbage collection isn’t supported on the iPhone and the Mac Obj-C garbage collector is documented not to do that – see Garbage Collection Programming Guide: Architecture, under How the Garbage Collector Works.)
If you mean self, then, yes, it stays intact over the lifetime of the object.
Although I have not gone indepth in the matter my views are as under:
Memory addresses of an object may not be static.
For example in Java, objects don't have pointers but references, the JVM might move around objects as part of its memory management scheme and might change the reference value in accordance to the moved object.
Also objects might be moved around as part of the Garbage collection procedure of the JVM.
Although I have not read of any official documentation on this, in case you come across the same you could post it here.
The same process might be taking place in .Net.
In the Cocoa Garbage Collection Programming Guide I'm not seeing quite the ironclad assurance that Ahruman makes above that an object address is guaranteed permanent:
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcArchitecture.html
Closed vs. Open Systems section:
'[In an open garbage collection system, collectors] reallocate and copy blocks of memory and update each and every referring pointer to reflect the new address. [...] Cocoa's garbage collector strikes a balance between being “closed” and “open” by knowing exactly where pointers to scanned blocks are wherever it can, by easily tracking "external" references, and being "conservative" only where it must.'
And with the general "dynamic" nature of the Cocoa runtime, I'd want a really explicit discussion of the subject in Apple documentation even for non-garbage-collected program. I don't find any statements along the lines of "the memory address of an object is guaranteed not to change" in searching the whole of developer.apple.com -- try Google with:
site:developer.apple.com cocoa "object's memory address" OR "memory address of an object" guaranteed OR permanent
And then there's that scary subject of... multi-threading (ahhhh).