Is there any performance difference between using class methods and instance methods to initialize an object?
In Apple's docs, I see the following, in the NSArray class (and I have seen this style in other classes too):
+ (id)arrayWithContentsOfFile:(NSString *)aPath
- (id)initWithContentsOfFile:(NSString *)aPath
The descriptions are very similar for each method.
Is there a performance difference?
Is one better than the other?
If they are both the same (in terms of performance), are there any times
that you would you use one method over the other?
Just curious. :P
The convenience constructor (+ version) will return an autoreleased value. Under ARC, this autorelease may be optimized away if the result is immediately assigned to a strong reference (using the objc_autoreleaseReturnValue/objc_retainAutoreleasedValue optimization).
The only time you need to be careful is with tight loops where using the + version may lead to lots of autoreleased objects getting created. If profiling reveals this to be a problem, consider using alloc+init instead inside such loops.
In general, you should go with whatever leads to cleaner code, which quite often means using the convenience (+) constructor.
Is there a performance difference?
Is one better than the other?
Not really, but it depends on exactly where you use them and what the surrounding context is.
If they are both the same (in terms of performance), are there any times
that you would you use one method over the other?
Personal preference mostly. The differences are in terms of memory management. The class method returns an autoreleased instance and you have no control over the zone it's allocated into. The instance method gives you control over those things.
Generally, and historically, on iOS you would avoid the autoreleased methods because you want to ensure that the memory used by the instance created is cleaned up quickly when you're done with it instead of being left until the pool is drained (because you usually don't know exactly when that will be). ARC reduces this concern though.
The difference between a class method and an instance method is that an
instance method requires an instance of the class on which it will
(generally) operate. The message to invoke an instance method must be
sent to an instance of a class.
For example
In Cocoa the NSString class has several class methods named
stringWithSomethingOrOther: that will create a new NSString object and
hand it back to you.
On the other hand, NSString also has many instance methods -
operations which really have no meaning without an actual instance to
work with. A commonly-used one might be the length method, which tells
you how many characters are in the specific NSString instance to which
the message is sent.
Suppose for another example-
#interface DeepsClass : NSObject
+ (void)myClassMethod;
- (void)myInstanceMethod;
#end
It can now be used like this : -
[DeepsClass myClassMethod];
DeepsClass *object = [[DeepsClass alloc] init];
[object myInstanceMethod];
Performance difference
Performance is almost the same in class methods & instance methods. Class methods are treated at runtime like any other methods (eg. instance methods), and while the Class may be loaded at runtime, the methods themselves are C functions, same as instance methods, and the POINTERS to those functions are cached, just like instance methods.
The only big difference is one give you autoreleased object and other don't.
The autoreleased object remains in the pool till the pool is released.
I love to use non-autoreleased object as whenever I'm finished with that object I just release it. In short you can dispose alloc-init object whenever you want, you just need a reference of this object.
//case 1:
for (int i = 0; i<1000; i++) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:#"path"];
//Do something with array
[array release];
}
//case 2:
for (int i = 0; i<1000; i++) {
#autoreleasepool {
NSArray *array = [NSArray arrayWithContentsOfFile:#"path"];
//Do something with array
}
}
//case 3:
#autoreleasepool {
for (int i = 0; i<1000; i++) {
NSArray *array = [NSArray arrayWithContentsOfFile:#"path"];
//Do something with array
}
}
Suppose your array takes 1KB, your first two cases will show peak of 1KB as objects are released immediately. In third cases your memory peak will go upto 1000KB and then comes back to zero after auto-released pool is released.
So it depends upon how you code.
Related
As the ios's document says that we should creating a new object following
NSObject *newObject = [[NSObject alloc] init];
And never create a object like this
NSObject *someObject = [NSObject alloc];
[someObject init];
It says that the init may possible return the different than alloc,so I'm confused that why or in what case they return the different object?Thanks!
This behavior is allowed so that your class could produce a stand-in object for the one being created. You may want to do that for several reasons:
Object Caching - If you need to create and release the same objects often, for example, when you create wrapper objects for numeric values, you could store object instances for reuse, and return them when requested. If you make your objects immutable, you could save significant amounts of memory by sharing your objects.
Returning a subclass - There are multiple design reasons for doing this, for example, to implement hidden functionality that is compatible with the interface of the object being returned, such as copy-on-write.
Returning nil - You are allowed to do this to indicate failure of your init function.
Take as an example the huge number of initWith... methods of the NSString class. Some are very specialised, and would like to return a specialised object. alloc cannot know that. So [NSString alloc] returns a generic NSString object, and each initWith method can return some specialised object instead.
Because
NSObject *someObject = [NSObject alloc];
All alloc does is allocate memory for the object. At this point in time there is no actual NSObject type, just a region of memory. This doesn't have any direct consequence if you immediately call init but you might fail to realize the init wasn't called and attempt to use the object without initialization.
The other answer has an even better reason, you might not get the same object back from init.
When it comes to accessing objects from different methods in the same class, from what I understand, these are two ways to do it. Given that I DO want to hold a property pointer to this object, which is the better way to go about this? I've been thinking about this for a while, and wondered if there is a preference consensus.
#1:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomethingToMyArray];
This method takes no parameter and accesses the array via its own property via self
- (void)doSomethingToMyArray
{
// Do stuff with/to the array via self.myArray
[self.myArray ...];
}
Vs #2:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomething:array];
This method takes an array and accesses the array via its own method parameter
- (void)doSomething:(NSArray *)array
{
// Do stuff with/to the array via method parameter "array"
[array ...];
}
I think it's primarily going to depend on what doSomethingToMyArray does and who calls it.
Fairly obvious comments:
if you want to do that to more than one array, you need to take an argument;
if what you're doing is actually logically more to do with the array than with your class (e.g. you've implemented randomisation of the order of the array) then it'd be better as a category on NSArray rather than being anywhere in that class at all;
if there's any possibility of subclasses wanting to redefine the manner in which the array is obtained then you'll want to invoke the getter somewhere;
similar concerns apply if a subclass or an external actor should be able to intercede anywhere else in the process.
Beyond those concerns there are a bunch of us that just prefer this stuff to be functional anyway — noting that you're doing something to the array, not with the array, in which case you'd tend more towards self.myArray = [self processedFormOf:array] (or self.myArray = [array arrayByDoingSomething]; if the category tip makes sense).
So, ummm, I don't think there's a clear-cut answer.
That depends on what you want to do, just by reading it:
doSomething:array
I would assume the above method takes ANY array and performs an action, whereas:
doSomethingToMyArray
with this method you are describing the intention of doing something to your instance's array. Inside this method (given that you followed Apple good coding practices and you synthesized your property to _myArray) , you could either go with:
[self.myArray message]
or preferably
[_myArray message]
Your second option is sort of silly. If you're storing a pointer in an instance, then it's so that you can use it later (within that instance) without needing to pass it around whenever you call a method.
This is also dependent on whether you're using ARC or not (use ARC if this is a new project). In a non-ARC project, self.myArray = foo; will do a very different thing than myArray = foo; (the self. syntax calls a property, which in many cases will correctly retain the thing you've assigned). In an ARC project, they'll generally have the same behavior, and there's less room for error.
Personally, in my ARC projects, I do not use the self. syntax from within a class, since it's just extra typing for the same effect. This ties in nicely with the new usage of #property, where you're no longer required to write a #synthesize block, and Objective-C will automatically generate an ivar for you, with the name of your property prefixed by an underscore, i.e. _myPropertyName. That makes it very clear visually when you're accessing code from outside the class (crossing the encapsulation boundary), where things will look like foo.bar = baz; versus inside the class, where it's just _bar = baz;.
IMHO, clearly, a function call would incur an extra overhead.
you would have to allocate an object pointer (though minimal) over the stack (extra memory)
Have to pass it (extra processing)
Property is actually a small function call unless you have made customizations to the getter. I also assume that compiler may have its own optimizations put in place for such accessors so that you can access them with minimal overhead, though I do not have any source to cite this.
I'm currently developing a game for iOS and we have a memory leak. Our project is ARC set up. I was wondering on how to ensure memory deallocation. One of the steps I was thinking of taking was convert code of the form:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
}
into:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
o = nil; // Explicit nil assignment
}
Is there a difference between the two? What other measures should I take to ensure a dealloc in an ARC setup?
We're using the Sparrow Framework.
Both methods do the same thing. Local objects are set to nil by ARC when they leave scope, so putting in a manual nil does nothing.
If you want to find a leak - you are far better off actually running it through Instruments with the Leaks tool and finding out what is being leaked, which will give you a better idea of what is going on. It's quite handy for finding retain-cycles.
As pointed out by Abizem, both methods lead to the same results, and require careful passes through Instruments. The results are not always easy to interpret.
In ARC, you should never see a leak - in the usual obj-C meaning -. Sometimes, iOS instruments can report a leak, but most if not all, this comes from the runtime, and I tend to regard them as beyond my control. What you can see however, is uncontrolled memory increase, which is typical of memory retention. Keeping strong pointers on objects is the obvious reason, which in my case has always been the consequence of : retain cycles in code blocks, and incorrect data structure cleanup, i.e. objects are created, then filled into arrays, dictionary, page control etc... but the later were not emptied properly during the app lifecycle.
Also image processing functions still use standard malloc/free directives embedded into internals UIGraphics lib, so in that case you explicitly need to free the memory (CGImageRelease, etc...). ARC will not help here.
hope this helps narrow down the problem, which as Abizem pointed out, should start with Instruments.
the following is unnecessary but (at least for me) the discussion in the comments was helpful and that's why I leave it
wrap the method in an #autoreleasepool. that will make it 99% percent sure it is being deallocated
-(void)methodMethod{
#autoreleasepool {
Object* o = [[Object alloc] init];
// Some logic
}
}
Both are the same.
A better solution to test your class:
- (void)testDealloc
{
__weak CLASS *weakReference;
#autoreleasepool {
CLASS *reference = [[CLASS alloc] init]; // or similar instance creator.
weakReference = reference;
// Test your magic here.
[...]
}
// At this point the everything is working fine, the weak reference must be nil.
XCTAssertNil(weakReference);
}
This works creating an instance to the class we want to deallocate inside #autorealase, that will be released (if we are not leaking) as soon as we exit the block. weakReference will hold the reference to the instance without retaining it, that will be set to nil.
I am trying to understand the instantiation process better. I understand that some classes need to be allocated and initialized (I have to create an object of the class) before I can use them, such as NSMutableArray. However, I am running into classes that I do not need to instantiate before I use them, such as NSDate and UIImage.
For example, I have always been instantiating NSMutableArray like this before I can use it:
NSMutableArray *myArray = [[NSMutableArray alloc]init];
With UIImage I can just skip instantiation and just do this:
UIImage *i = [UIImage imageNamed:#"image.png"];
Are there any rules or tell-a-signs for when I can just use a class without instantiating and when I have to instantiate? I'm trying to see if there is a quick way of knowing this.
Thanks!
You are always instantiating an object in either case. It is just that the UIImage class provides some static convenience methods that hide the rather ugly alloc/init process. Even NSMutableArray has [NSMutableArray arrayWithCapacity:numItems] which still does 'alloc', 'init' inside of it but also sets up an initial capacity (for performance reasons). The best way is to peruse the docs, looking for static class methods, or seeing if autocomplete has any methods that begin with the thing you are making, e.g. [UIImage image...] and [NSDate date...]
In general, my own rule of thumb is if the object is only going live within that method and not be used outside the scope of that method, I'll use a creation API for an object thats autoreleased before I instantiate a new object.
But, if you need to access the object anywhere else outside of the scope of the method, you must instantiate it and have the memory retained and stick around.
In your example above, if you're taking "UIImage * i" and dropping it into an image view or doing something with it only within a single method, then "imageNamed" is perfectly appropriate.
If you need to keep "UIImage * i" around for anything outside the scope of the method, use it's designated initializer instead.
I have a pool of objects I keep inside an NSMutableArray so if any other objects want to reference them instead of creating new objects I will simply give it a reference to an object I have already created.
In the past I would monitor retain/release calls on these objects, and when they reached a retain count of 1 (my array only) I would remove them from the array. However I am struggling to do this with ARC because it doesn't let me monitor retain/release, how would I go about doing this?
Creating a way to manage objects based on release/retains calls, it's dangerous. If Apple happens to change the way it works, you are screwed. And apparently, that's what happened, when you start using ARC. There are two things:
1) You want to keep the objects inside the NSMutableArray independently if they are being use by other objects or not. In that case, just create a __weak reference to that objects, and in that way your object, that is inside the NSMutableArray, is kept alive.
2) Once there are not references to the object, just remove it from the NSMutableArray. Add to the NSMutableArray a __weak object. Once the strong one is release, the one inside the array will be as well, although I don't really like this approach as I find it dangerous. If you go for this option, use this to store the objects:
NSValue *weakObject = [NSValue valueWithNonretainedObject:anObject];
[array addObject:weakObject];
In the end, you can simply remove ARC from that specific file, and you can keep the monitoring.
I wouldn't bother with such a complex system. Just work with strong and weak properties and don't try to second guess performance. You are trying to build a memory management system yourself which makes little sense with ARC around. Creating and deleting objects is generally a tiny percentage of performance of any objective-c app; after years of using Instruments to monitor performance I don't worry about this part any more.
First, you should write simple code, intended for humans.
Do not worry about such performance issues until you have proven (via instruments or some other measure) that this is a critical bottleneck.
That said, creating certain objects can be really expensive, so keeping a cache for certain objects is not in and of itself a bad idea. However, you should never rely on reference counts, even in non-ARC code. Apple docs are very clear about this.
The alternative, as Jacky pointed out is a weak reference. Unfortunately, you can not put a weak reference into standard collections (though, ironically, you can put them in C++ collections and they will be managed correctly).
However, you can create a simple wrapper class to hold a weak reference.
#interface WeakWrapper : NSObject
#property (readonly) id object;
- (id)initWithObject:(id)object;
#end
#implementation WeakWrapper {
__weak id _object;
}
- (id)object {
return _object;
}
- (id)initWithObject:(id)object {
if (self = [super init]) {
_object = object;
}
return self;
}
#end
You can then place these objects inside collections, and then...
WeakWrapper *wrapper = // get the object from the collection
id object = wrapper.object;
if (nil == object) {
// You know the object that was being referenced no longer exists
// so this wrapper can be removed from the collection and destroyed.
}