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: Tue, 30 Dec 2003 18:51:36 -0800
At 01:22 PM 31/12/2003 +1300, Denis Stanton wrote:
>> Summary reporting is always a problem due to the constraints of
>> processing speed and memory usage. One thing you might want to
>> consider is ReportMill (http://www.reportmill.com/). It is free to
>> use if all you need are HTML reports.
>
>Well that's new to me. I had the impression that ReportMill was fairly
>expensive, or at least priced high enough to make it uneconomic for my
>needs.
>
For PDF reporting it may be priced too high. Even for that you need to
compare the cost of developer time with "free" products vs developer time
with RM. ReportMill has made HTML reporting free as an inducement to learn
their product. Check the link on their homepage. Well worth your time to
look at this.
>> Barring that, 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). If there are a lot of bookings this can chew up a lot of
>> memory (e.g. when your client suddenly decides to see what happens
>> when they run the weekly summary over a whole year :-).
>
>They are likely to run this report to cover either a six month or one
>year period. The speed problem only becomes apparent for the one-year
>report. That means a lot of bookings in memory so I was attempting to
>process one agent at a time.
>
If you go that route, then fetch all bookings for that agent in the time
period and process them as a batch. If that is too large, then turn it on
its head and try one day at a time.
>> You could start fetching daily sets of data and getting aggressive
>> with EOF memory management to control this.
>
>Any hints about getting aggressive with EOF memory management would be
>of interest.
>
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=memo
ryManagementOfEOs
Also generally relevant links at:
http://wodev.spearway.com/cgi-bin/WebObjects/WODev.woa/wa/Main?wikiPage=WebO
bjectsFrequentlyAskedQuestions
>My report uses a simple repetition to work through the agent array.
>
>DisplayList: WORepetition { list = agentArray; item = agent;}
>
>Then I have a setAgent method that is implicitly called by the
>repetition.
>
>protected void setAgent(Agent inValue) {
> bookings() = new NSMutableArray(
>EOQualifier.filteredArrayWithQualifier(agent.bookings(), qualifier) )
>}
>
>The repetition encloses lines with values mapped to @sum calculations
>on the bookings array
>String1: WOString { value = email@hiddenrice; }
>
Noooooo... :-) Your goal should be to touch each booking exactly once.
@sum is equivalent to a slow for loop. Not to mention the fact that the
bindings might get synchronized (calculated) multiple times (not for the
first display). All that adds up to bad, bad performance. Be very, very
careful about using a method that takes any significant time to execute in
a WOD file binding. Your code, at best, is equivalent to:
for each agent
for each booking calculate stat 1
for each booking calculate stat 2
for each booking calculate stat 3
for each booking calculate stat 4
for each booking calculate stat 5
for each booking calculate stat 6
for each booking calculate stat 7
for each booking calculate stat 8
for each booking calculate stat 9
for each booking calculate stat 10
for each booking calculate stat 11
And up to three times that effort. Calculate the summaries outside of
value synchronization in the R-R loop. You will usually get better
performance by writing an optimized summarization routine and then doing a
straight forward dump than calculating on the fly. What you want is:
for each agent
for each booking
calculate stat 1
calculate stat 2
calculate stat 3
calculate stat 4
calculate stat 5
calculate stat 6
calculate stat 7
calculate stat 8
calculate stat 9
calculate stat 10
calculate stat 11
However, as Agents do not share Bookings, with the assistance of Agent this
can be reduced to:
for each booking
calculate stat 1
calculate stat 2
calculate stat 3
calculate stat 4
calculate stat 5
calculate stat 6
calculate stat 7
calculate stat 8
calculate stat 9
calculate stat 10
calculate stat 11
The last two are more or less equivalent in time consumption, but the
latter seems easier to understand as I envision the code.
> I am assuming that since the setAgent() method recreates the bookings
>array for each agent then Java will take care of the memory management,
>keeping just one agent's bookings in memory at a time.
>
Memory might be OK like this but performance will not be.
>> Once you have all the bookings, you can get all the agents from:
>>
>> NSArray agents = new
>> NSSet((NSArray)bookings.valueForKey("agent")).allObjects();
>>
>> Then run a loop over all the bookings, tell the agent to calculate
>> stats for them:
>> thisBooking.agent().accumulateStatsFor(thisBooking);
>> You will probably also want a resetStats() method to zero these out.
>>
>> You will need to add instance variables to Agent to hold the 11
>> totals. Don't put these in the EOModel, they are just transient
>> values for reporting. The code to determine which booking affects
>> which stat goes in Agent. This keeps the functionality fairly well
>> partitioned and keeps processing time down as you have a minimal
>> number of fetches and touch each booking once in one loop.
>>
>> Following this, sort the list of agents and report away!
>
>Do you see an advantage in accumulating into instance variables in each
>Agent, then sorting and printing, as opposed to sorting the agents
>first (I specify the sort in the fetch) and then calculating and
>printing one line at a time by defining the display as for String1
>above?
>
In my way there is no need to sort or group the bookings and each booking
is examined precisely once in loop. The agents group implicitly by
calculating their own stats. It also a better OO design (IMHO) as the
responsibility for calculating the stats is in the Agent business object
rather than the UI. What are you going to do if different agents start
negotiating different deals and thus different calculations? You might
even want to get the booking involved in the calculation.
Sorting the agents before or after calculating the stats is irrelevant.
>"Extract - (calculate) - Sort and Print" seems more like the way I used
>to work in the pre-OO days (I was a Cobol programmer for 15 years).
>
Cobol. Shudder. I remember doing that. ;-)
Unwinding loops is a standard optimization technique from way, way. Making
the agent calculate the stats is an OO point of view. Even if the page
accumulates the stats, unwinding the loops and NOT using bindings to
calculate is good WO/optimization practice.
The other conceptual advantage is that you are reporting on Bookings no
Agents. So rather than fetch Bookings piecemeal, Agent by Agent, do one
fetch (sorting by agent if you wish) and then calculate and print. By
using WOD file bindings you are calculating *while* you are printing in an
inefficient manner.
>I
>have been trying to avoid storing calculated values when the
>calculation itself can be defined as an instance method.
>
>> HTH
>
>BTW. What is HTH? Happy "T" Holiday?
>
Hope That Helps.
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.