Re: can I use fetch spec to filter an array?
Re: can I use fetch spec to filter an array?
- Subject: Re: can I use fetch spec to filter an array?
- From: Chuck Hill <email@hidden>
- Date: Wed, 31 Dec 2003 17:05:13 -0800
Hi Denis,
At 01:30 PM 01/01/2004 +1300, Denis Stanton wrote:
>
>Lots to think about here. I'm going to consider all this off-line for a
>while.
>
Yes, it can get complex.
>Some comments:
>On Thursday, January 1, 2004, at 12:04 PM, Chuck Hill wrote:
>> At 10:19 AM 01/01/2004 +1300, Denis Stanton wrote:
>>> OK, so my biggest error was to apply @sum 11 times for each agent,....
>>
>> I don't know if that was your BIGGEST mistake (see below)
>
>OK, I knew I was setting myself up for that one :-)
>
Grin.
>I put in log messages to count the milliseconds at several point in
>each loop. The log messages themselves distorted the timings, but what
>I did observe was:
>On the first attempt, loading takes much longer than calculating,
>particularly when there are many booking per agent (some agents have
>only one booking, some have 200)
>On the second attempt the two phases take similar times.
>This is consistent with the different speeds of DB and memory access.
Yes. Fetching the data (especially if done one at a time) and creating eo
objects out of the rows can consume a fair bit of time.
>There is an apparently random delay cropping up every now and again,
>making the loop take much longer for some agents. It is not
>consistently associated with particular agents - the next attempt will
>be different. My guess is that this is garbage collection cutting in
>and taking up some cycles.
>
I agree, that sounds like garbage collection. There is not much to do
about this other than allow more memory and/or try to move the collection
cycle elsewhere. Neither may be very effective.
>> You've overlooked a crucial part of my previous message:
>> "...I'd fetch all the bookings in the time frame with a fetch spec set
>> to
>> prefetch all the agents. This should give you all the data that you
>> need
>> in two fetches (one for bookings, one for agents).
>
>Does this mean that I could fix the slow response time on the first
>execution by simply reading all bookings (within date range) into an
>array before beginning the other processing, even if that array is not
>otherwise used in my program?
>
Yes, that should help provided this is in the same EC as your reporting
data. However, if you are interating over the bookings() array on Agent it
will also pause to fetch all the other bookings to determine if it needs them.
>A single fetch is more efficient that
>the multiple fetches that may be requested when my code seeks to follow
>the relationships.
And that can make a fairly large difference!
>Would EO figure out that all the bookings were now
>available in memory and this save the time it was spending on trips to
>the database? A quick test suggests that this does not help.
>
It should. Check to ensure this is happening before and in the same EC
(will also work in a different EC depending on the fetch timestamp). Maybe
something else is doing the fetch again or invalidating the objects?
<bunch of code>
> That's approximately what I have, but with rather more typing than I
>am accustomed to. Does the code above offer any advantage over the
>code below? Maybe you are just trying to give the most general case,
>or is there a penalty on using qualifierWithQualifierFormat?
>
I was just allowing for more, and optional, search criteria. Just a
reaction from some of the stuff I've been doing lately. :-)
qualifierWithQualifierFormat is fine to use if the qualifier is known
beforehand. While I'm on the topic, there is no need for this:
NSArray bookings = new
NSArray(editingContext.objectsWithFetchSpecification(fetchSpec));
Just use
NSArray bookings = editingContext.objectsWithFetchSpecification(fetchSpec);
>> Notice carefully that I am *not* using agent.bookings().
>
>agent.bookings() looks so easy! I now see it as a potential trap
>
And you are not the first to have fallen in it! :-(
>> If only some of
>> the bookings are on this report, there is no need to fetch them from
>> the
>> database, nor to consume large amounts of memory by turning them into
>> objects. You may, in fact, discover that you do not want bookings()
>> as a
>> class property of Agent as each time it is referenced it will pull in
>> (at
>> least a reference) to each and every booking ever associated with an
>> Agent.
>
>Now you've got me thinking. I have many relationships in my model
>because that seemed the logical way to organise the data and still have
>easy access to it. I wonder how much overhead I am adding if EO is
>pulling in references for relationships that are rarely followed.
>
It is a hard decision to make. Having the relationships make data access
much easier and EOF keeps everything updated. It depends on how and how
often you access the relationships and how much data there is. Assuming
you have not turned deferred faulting off then if you never access
bookings() it should incur no penalty. If you so much as ask for
bookings().count() it will fetch all the primary keys. Once you start
asking for specific booking data it will start fetching the bookings.
Pre-fetching relationships and batch faulting can alter this to make it
more efficient. If you know there are a lot of objects in a relationship
and you know they are probably not already in memory then you can prod EOF
into doing a bulk fetch with code like this:
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=EODa
tabaseContext.batchFetchRelationship
e.g.
preloadRelationship(agents, "bookings");
Useful related tips here:
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=Spee
dingUpSlowEOs
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=HowT
oBatchFetchingEOFaults
>> Because when you click the link to get off of this page WO does not
>> know
>> which component it is for. It must reevaluate each repetition and each
>> conditional so that it can ask the child of each if it is responsible
>> for
>> that action.
>
>This seems like a very bad thing. I click the submit button in a
>little query form at the top of the page and WO has to re-expand the
>whole rest of the page before it can figure out that the submit button
>was clicked?
>
No, just until it finds what was clicked. This is why it is a bad idea to
return null from action methods: WO keeps looking for the component
responsible for the action. With the query form at the top it should stop
fairly quickly. If you put the form inside a table or at the bottom of the
page it can be a different story. As I said before, Direct Actions can
help but can be trickly to use in this situation. Moral of the story:
don't bind to slow methods.
>This page has no links from inside the repetition. There
>seems to be no reason to re-expand the page.
>
It is just doing a tree traversal until it finds the correct action. If
your action method has
return null;
that is the cause. Do this instead:
return context().page();
Chuck
--
Chuck Hill email@hidden
Global Village Consulting Inc. http://www.global-village.net
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.