I'm mainly wondering about the affect that garbage collection would have on performance. Is the use of garbage collection frowned upon for release apps?
Another concern that I can think of is that using garbage collection could lead to sloppier programming.
Do you use garbage collection in your apps?
Garbage Collection is used in many production quality applications. Xcode, Automator, System Preferences and several other system applications are GC'd, and you can expect that trend to continue over time.
As well, many developers have embraced GC and are using it exclusively in their applications. Intuit's new versions of Quicken and QuickBooks for the Mac are garbage collected, for example.
There are a number of advantages of GC, too. Off the top of my head and from personal experience:
it makes multithreading easier; a simple assign is an atomic declaration of ownership
it offloads a bunch of memory management to other cores; it is naturally concurrent and offloads a bunch computation from the main thread (or computation threads)
in many cases, allocation and deallocation can happen entirely within the context of a thread, thus eliminating any need for global synchronization or locking
the collector has gotten faster with each release of Mac OS X and that trend will continue (just as it has with the rest of the system). By offloading more of your app's computational load to the system provided frameworks, your app will gain more and more from optimizations to the underlying system.
because the collector has intimate knowledge of the object graph -- of the pointers between objects -- in memory, it makes analysis and debugging significantly easier. Instead of "where did this dangling pointer come from?", the question is now "Give me a list of reasons why this object is sticking around longer than I think it should?".
This isn't to say that there isn't work to do to make your application work optimally under GC. There certainly are such tasks!
Garbage collection has been around since the 1960s and is used in many released applications. All .NET apps use garbage collection. Apple uses libauto in Xcode.
Garbage collection generally leads to better quality apps in Cocoa since the developer is freed from the memory management burden. There are tons of Cocoa apps that leak! (though it may not a significant amount of memory)
I tend to use gc since since I can turn around my apps faster and don't have to worry about messaging zombie objects!
I use GC whenever I can, because the best code of all is the code you don't have to write in the first place. Also, as Bbum pointed out above, running under GC means that you have far more information available for performance analysis, should you need to debug any bottlenecks.
Garbage collection is recommended for any new Cocoa applications, and Apple eats its own dog food by using it in Xcode. Performance is an interesting situation, because while you're most likely going to be consuming more CPU cycles overall, the application may actually end up faster in some areas due to multithreading of the collector and the simplification of accessor methods.
Computers are made to do work for us. Cocoa's reference counting is usually easy to manage, but garbage collection is one more thing it can do now--let the machine do the work so you can focus on things that matter!
Like the others, I would strongly recommend using GC. The performance overhead usually is negligible! I don't need to repeat the benefits as stated by other users.
However, I would strongly encourage writing libraries, as opposed to applications, to run in a non-GC mode as well. Some environments cannot run GC code, the iPhone being the notable one; so if you created an internal library for yourself, that you envision reusing it later for an iPhone app, then I would recommend designing it so it would work in a non-GC environment as well.
Converting a GC code to non-GC code is much more difficult than the other way around!
Related
I wonder how the professional application that provided to customer is such elegant , smooth and less or no application crash. because I always see the problem is mostly about memory leaking, NSZombie or not good enough performance.
I see it's great to fix some problem with Instruments Tool. But I just be familiar with memory leaks and zombie template. Of course, I think there are other interesting tool to trace and fix our application better. (System usage, Automation Testing, etc.. Any ideas?)
My question : What's the best strategy to sharp your application with Instruments? Recommend instruments template or any suggestion?
Let's share your experience and discuss!
*UPDATE : * May I ask more question, Should I edit this question to the wiki? It should be more than question that we can share strategy.
I mainly (about 98.2% of the time) use the Leaks and Allocations templates. Also, many people don't know - but in Xcode 4, you can start the app using instruments right from Xcode. From the top menu, just choose Product -> Profile.
Also - even when using ARC, you should still be conscious of how you are using memory and how you are allocating objects. Many times, ARC was doing its thing just fine and yet a small programming change in my code resulted in much less allocated objects. ARC will help you when writing code, but it is not an excuse for not testing and profiling your applications to make them as efficient as possible.
Yes, Instruments is critical. ARC mitigates some of the worst memory problems. Analyze (on Product menu) is also under-appreciated, too.
Check out program 123, Improving the Stability of Your Apps, in WWDC 2011 in the App Frameworks section, which has a nice discussion of other issues that can affect the stability of your code (I especially think the discussion of testing is good).
Finally, elegance is not a product of a tool, but rather of good design. It takes a surprisingly amount of work to make a product that is elegant. Embrace the HIG and the broader philosophical themes contained therein. Also, do code and design reviews with developers that you respect.
The CPU sampler (Time Profiler) will tell you where your program is spending its execution time. If your app is 'slow', this instrument can often help you determine where the problem time consumers are, and (if you understand your program) how you can remedy those problems.
Run this instrument regularly in order to understand your programs as well as the implementations behind the abstractions they depend on -- don't wait until a problem arises.
You can use the CPU sampler to record the callstacks of your programs' threads. This is recorded at a high frequency. The sampler displays information such as the functions that are taking the most time and what percentage of the time they are taking. You can charge libraries or functions to their callers, effectively choosing the granularity you'd like, or hiding what you cannot alter. Once you've found the functions/methods you are interested in, you can view the source file in Instruments, and it will break down what's taking so long for you.
Apple introduced sweet feature called Automatic Reference Counting(ARC) that makes almost all memory control for you. You just need to set weak/strong parameter of properties. And it eliminates almost all problems with memory leaks.
And as for tools - I don't know any other app other than Instruments. Instruments has all... Instruments:) I need, to do tests with.
After migrating my app to ARC using the migration tool and resolving all pending issues a quick test in the Allocation instrument revealed that pretty much anything I do in the app is leaking memory.
It's a pretty big app and migration took 2 hours to complete (including checking every change which I did - all of them looked fine!)
I checked all the compiler flags twice to make sure ARC is really enabled for every file and on the project level.
Previously to migrating to ARC my app was totally fine. There was absolutely no heap growth when taking Heapshots by repeating the same action multiple times. It was 100% leak-free, there was no abandoned memory. It was perfect. Now it's one huge leaking thing like if there was no tomorrow.
Any idea what's going on?
You haven't shown any code here to highlight parts of your application that are causing objects to accumulate in memory, so it's hard to provide a specific answer to your situation. However, there are some broad suggestions that I can provide based on my experience in migrating several projects across on Mac and iOS.
In another answer, I describe in detail several areas of memory management that you'll still need to watch out for under automatic reference counting. The primary concerns here are retain cycles and Core Foundation objects (or other non-Objective-C memory allocation).
Given that you had an application which did not accumulate memory on repeat actions before and was cleanly ported through the ARC migration tool, retain cycles are more likely the problem than improper bridging, etc. with Core Foundation. The migration tool tends to highlight problematic areas with Core Foundation and catch those before they become an issue. How to deal with them may be tricky, but you at least know they're there.
Retain cycles can be subtle bugs to track down. Look for delegates that are set using strong instance variables or properties, rather than weak or unsafe-unretained ones. Examine your use of blocks or block-based notification observers, because they can hold on to references to the objects that create them (particularly in the case of the observers) and create cycles. Check for objects further down a navigation hierarchy that use strong references to point to ones higher up.
Use Instruments to track down the specific objects that are accumulating via the Leaks and Allocations tools. In the latter, use heap shots between repeated actions to see which objects are created and still alive after each pass. You should also be able to identify where those objects are allocated, hopefully leading back to what's grabbing an incorrect strong reference.
The Leaks instrument has a new retain cycles detector, which can be seen by going to the lower panel and changing the "Leaks" popup to "Cycles & Roots". This doesn't catch everything, but it can help.
I've now moved multiple projects on Mac and iOS to ARC, including Mac applications that had been using GC, and in each case the applications have been better off for it. The process has exposed bugs that I had missed for years in my memory management, cut on average ~3% of my project code, and has led to some significant performance increases in my previously garbage collected Mac applications (I haven't benchmarked my iOS ones yet).
Background: I'm (jumping on the bandwagon and) starting learning about iPhone/iPad development and Objective-C. I have a great background in web development and most of my programming is done in javascript (no libraries), Ruby, and PHP.
Question: I'm learning about allocating and releasing memory in Objective-C, and I see it as quite a tricky task to layer on top of actually getting the farking thing to run. I'm trying to get a sense of applications that are out there and what will happen with a poorly memory-managed program.
A) Are apps usually released with no memory leaks? Is this a feasible goal, or do people more realistically just excise the worst offenders and that's ok?
B) If I make a NSString for a title of a view, let's say, and forget to deallocate it it, does this really only become a problem if I recreate that string repeatedly? I imagine what I'm doing is creating an overhead of the memory needed to store that string, so it's probably quite piddling (a few bytes?) However if I have a rapidly looping cycle in a game that 'leaks' an int every cycle or something, that would overflow the app quite quickly. Are these assumptions correct?
Sorry if this isn't up the community-wiki alley, I'm just trying to get a handle on how to think about memory and how careful I'll need to be. Any anecdotes or App Store-submitted app experiences would be awesome to hear as well.
I've taught courses on Cocoa development, and memory management is the second thing I teach (the first being C pointers). My experience has been that if a Cocoa programmer doesn't understand memory management, then he never amounts to much of a Cocoa programmer.
In other words, learn memory management. You won't regret it.
Follow the patterns, and memory management is rarely the biggest roadblock in Cocoa.
However, I'm going to be a contrarian here: your sense is mostly correct. Leaking one NSString used as a label somewhere is not going to hurt anybody. Most apps of any complexity have multiple singletons around in the world holding state for the entire life of the app, and that's OK too (well, better, because it's explicit). So no, accidentally leaking a string once isn't going to kill you. Leaking big things (images, textures, file content data) will hurt you, though-- Apple doesn't guarantee any minimum or deterministic amount of memory for your process on the iPhone OS platform, so one or two of those leaks might result in users seeing frequent "crashes" in the field that you don't always see during development.
Be vigilant, use the patterns, and use the tools, and you'll be OK.
Your should never leak memory.
Consider: You today write some code that leaks memory only once during the execution of a program. Tomorrow, you reuse that code in some other way and it is executed many times. The leak is then problematic. Finding that leak may be very difficult. Much more difficult than making sure to always free your memory the first time you wrote the code.
Save yourself and others a headache down the road: always free your memory.
It is very important. Apple offers a tool for memory leak detection called Instruments.
This topic has previously bean discussed here as well: Memory leak detection tools in XCode
More important than life itself :p
Seriously though, just follow the rules in the links below and you'll be ok.
It becomes second nature after a while.
http://theuntitledblog.com/2010/05/25/objective-c-memory-management-rules/
http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html
Let's say you are implementing an interpreter for a GCed language in a language that is GCed.
It seems to me you'd get garbage collection for free as long as you are reasonably careful about your design.
Is this generally how it's done? Are there good reasons not to do this?
Language and runtime are two different things. They are not really related IMHO.
Therefore, if your existing runtime offers a GC already, there must be a good reason to extend the runtime with another GC. In the good old days when memory allocations in the OS were slow and expensive, apps brought their own heap managers which where more efficient in dealing with small chunks of data. That was one readon for adding another memory management to an existing runtime (or OS). But if you're talking Java, .NET or so - those should be good and efficient enough for most tasks at hand.
However, you may want to create a proper interface/API for memory and object management tasks (and others), so that your language ("guest") runtime could be implemented on to of another host runtime later on.
For an interpreter, there should be no problem with using the host GC, IMHO, particularly at first. As always they goal should be to get something working, then make it work right, then make it fast. This is particularly true for Domain Specific Languages (DSL) where the goal is a small language. For these, implementing a full GC would be overkill.
So I finally dusted off my Objective-C/Cocoa books.. turns out they are nearly 7 years old! With Objective-C 2.0 now having garbage collection, how important are the chapters on Memory Management?
How much of a difference has Garbage Collection made?
Memory management is still really important to understand. If you're targeting an older OS, you need to do memory management. If you're using an older library, you need to do memory management. If you drop down to the Core Foundation level, you (may or may not) need to do memory management.
If you're programming for iPhone, you need to do memory management.
The garbage collector in Objective-C is outstanding - and if you can be using it, you most definitely should be - but it just doesn't cover every programming situation yet.
Some Cocoa technologies, such as Distributed Objects, PyObjC (the Python-Objective-C bridge) plugins and CoreImage (at least last I heard; this may have been fixed) don't play well with Garbage Collection. If you're using these technologies, you will still have to use traditional memory management. Of course, as others have said, you still need to use traditional Cocoa memory management (reference counting) if you're supporting OS X 10.4, or the iPhone in your code.
On the other hand, the new GC can be very nice. It's not a free lunch however; you still need to understand the semantics of the GC system, its patterns and its limitations...just as you do with any technology.
Since many thrid-party frameworks may not yet support GC, it's probably best to still understand the reference counting system. If you follow the simple rules for object ownership given in Apple's memory management guide, you should always be OK.
If you're programming the iPhone platform, you need to know retain/release, because Cocoa Touch does not have GC.
If you're going to use Core Foundation, Core Graphics, most of Core Services, or any other CF-based API, you need to know retain/release, because CF-derived objects are not GC'd by default (and you must explicitly put them out for pick-up, anyway).
If you're going to use any of the POSIX APIs or any of the rest of Core Services, you need to know alloc/free memory management. You don't even get reference-counting. (Exception: Icon Services, which also has reference-counting. APIs born from Carbon are a mess.)
So, in a word: Yes.
It depends. If you're planning on ignoring 10.4 users, then you might not have to worry about it; but Objective-C 2.0 isn't available on 10.4 and below, so you still have to worry about memory management on those platforms.
That said, memory management is always a useful skill, and it's not that hard in Cocoa anyway, so it's not a bad skill to pick up.
It is probably worth learning about the concepts that underpin Cocoa memory management, as it's still useful in certain situations. The iPhone OS, for example does not support garbage collection. There may be other situations where it is advantageous to use manual memory management, and it's useful to have the ability to make that choice
Understanding Cocoa's excellent memory management concepts will help you with the concept of memory management in general. I've copied the autorelease concept into a few C++ projects and it worked great. Apache and Subversion are examples of other software that also uses autorelease.
Personally I find retain/release/autorelease to be just the right level of abstraction for me. It's not magic, so if I really need to do something weird, it's easy to do so. On the other hand, the rules are so simple that it becomes second nature, to the point where you eventually just don't think about memory management anymore, it just works.
Add to this the fact that, as mentioned above, only most of Cocoa supports garbage collection, while what you are writing is C, so any code you write and/or use that isn't Cocoa will need to be manually managed. This includes CoreAudio, CoreGraphics, and so on.
(Yes, CF objects work with GC, but only if you explicitly enable it for each object, and I found it hard to learn the GC-CF rules)
In summary: I never use the garbage collector myself (and the only time I did so it was very painful, as I had some C++ and CG in the mix), and as far as I know, most Cocoa coders are very used to retain/release/autorelease and use that.