Re: DateCreated in CoreData - Best Method?
Re: DateCreated in CoreData - Best Method?
- Subject: Re: DateCreated in CoreData - Best Method?
- From: Greg Herlihy <email@hidden>
- Date: Sun, 12 Mar 2006 22:25:15 -0800
- Thread-topic: DateCreated in CoreData - Best Method?
Given any set of potential implementations, the best advice is always to
pick the one that mostly closely matches the ideal behavior. For example, in
this case, if the creation date and modification date should ideally be
identical for a newly-created record - then whichever implementation makes
such a guarantee should be the one selected. It makes no sense to select
some other, suboptimal way of doing things solely out of concern for its
performance. Such concerns should not comprise an application's behavior -
unless and until its performance has been measured. Otherwise, trying to
improve a program's performance without profiling its execution is imply a
waste of time.
There is value however in being able to "eyeball" source code and to be able
to identify wasteful practices that could easily be avoided. In other words,
while there is no reason for prematurely optimizing code, there likewise is
no reason to "pessimize" it unnecessarily either. And since the three
choices described illustrate one way to avoid such "pessimization", I have
analyzed them below.
On 3/12/06 7:33 PM, "Steve Cronin" <email@hidden> wrote:
> Folks;
>
> I've got a CoreData entity for which I want to implement a
> 'dateCreated' field.
> This entity will be slammed by an import process [potentially ~200K
> records per night).
> So I want to be ABSOLUTELY certain I'm doing this as cleanly as
> possible.
> [Not of course that I try do otherwise elsewhere but, ..... well,
> hopefully you get my drift]
>
> So I've got 3 proposals in my brain:
>
> 1) - (void)awakeFromInsert {
> NSDate *now = [NSDate date];
> [self setDateCreated:now];
> [self setDateLastModified:now];
> ________________________________________________
> 2) - (void)awakeFromInsert {
> [self setDateCreated:[NSDate date]];
> [self setDateLastModified:[NSDate date]];
> ________________________________________________
> 3) - (void)awakeFromInsert {
> [self setDateCreated:[NSDate] date];
> [self setDateLastModified:[self dateCreated]];
I assume the second line of Option #3 should read:
[self setDateCreated:[NSDate date]];
> ________________________________________________
>
> 1) This has the advantage of both attributes getting exactly the same
> value in all circumstances at the cost of initializing an instance
> variable and an NSDate class every time.
First some terminology: "now" is a local variable - not an instance
variable. Instance variables are per-object variables declared in a class's
@interface section. Generally NSManagedObject subclasses should avoid
declaring their own instance variables. Local variables on the other hand
can - and should - be declared and used freely.
To compare these three options, simply count how many function calls each
makes. There is no other overhead to consider. In particular, once a
function call completes there is no additional cost to store its result in a
local variable. Because if a program does not store the result, then the
result is simply thrown away.
Now throwing away something that will shortly be needed is a wasteful
practice. Imagine driving to the supermarket, buying a gallon of milk,
driving home, drinking a glass, pouring the rest of the milk down the drain,
then driving back to the supermarket, buying another gallon of milk just
like the first, driving home - and doing all of this just so that you can
drink two glasses of milk.
Replace "gallon of milk" with "current time" and "supermarket" with "NSDate"
and it should become evident that option #2 essentially follows the pattern
described: it goes out to get the current time from NSDate and does so twice
- because it does not have to foresight to keep the date retrieved the first
time - around long enough to be used a second time.
Option #3 follows a slightly different, but no more efficient, pattern:
instead of pouring the gallon down the drain, in this scenario you decide
instead to drive across town and leave the gallon of milk in a friend's
refrigerator, return home, then drive back across town to the friend's house
to retrieve the milk in order to pour the second glass.
So of the three choices, only option #1 eliminates all of this time spent
driving around since it retains the gallon of milk between glasses - and
keeps that gallon at home - the same place where it will be needed to pour
the second glass.
> 2) This has no instance variable but there are 2 NSDate class
> initializations and the values are not guaranteed to be exactly
> identical.
#2 makes calls the same three functions as #1 - however it calls one of
those functions twice.
> 3) This has no instance variable and only 1 NSDate initialization and
> both values are guaranteed to be identical but has the overhead of
> [self ..].
#3 makes the same three function calls as #1 but calls an additional, fourth
function.
> I'm hoping knowledgeable folks might chime in on why one of these (or
> some other strategy) is distinctly better than the others. [stack
> management, compiler wisdom, autorelease behavior, messaging
> overhead, school of hard knocks...]
So in summary: #1 calls three functions, #2 and #3 call the same three
functions as #1 - but each makes a fourth function call of their own. So
clearly #1 cannot be any slower than #2 and #3 and naively one would expect
it to be 33% more efficient (its 3 vs. 4 function calls for the other two).
While 33% sounds like a significant difference, it's unlikely to matter. The
reason is that calling [NSDate date] has negligible overhead to start with.
So the potential for speeding up these routines is minuscule. On my G5, a
program that calls NSDate 200,000 times is done in less than 1/3 of one
second. So the potential time saved per record translates roughly into
0.0000015 seconds (or halfway between one and two millionths of a second).
But even though the inefficiency in this example is likely insignificant,
there may well be other cases where the same pattern ends up wasting a great
deal more time. So it is always a good idea to avoid unnecessary
inefficiencies - since in the absence of actual performance measurements -
it's very hard to know when an inefficient implementation is one that will
matter.
Greg
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden