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: Denis Stanton <email@hidden>
- Date: Thu, 1 Jan 2004 10:19:26 +1300
Hi Chuck
Happy New year (I'm writing to you from 2004)
On Wednesday, December 31, 2003, at 03:51 PM, Chuck Hill wrote:
At 01:22 PM 31/12/2003 +1300, Denis Stanton wrote:
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.
OK, so my biggest error was to apply @sum 11 times for each agent,
where each @sum causes a loop through all bookings for that agent.
for each agent
for each booking calculate stat 1
for each booking calculate stat 2 ...
You've suggested two alternative strategies, each of which requires
that a booking be read only once.
for each agent
for each booking
calculate stat 1
calculate stat 2...
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
I have implemented the first of these. It made sense to me to add code
to the Agent class to accumulate stats for each linked booking of the
one-to-many relationship.
It made no measurable difference. The timing of consecutive executions
varies so much without changing the code that I cannot get an accurate
comparison.
The last two are more or less equivalent in time consumption, but the
latter seems easier to understand as I envision the code.
I didn't try the second alternative, which you said seemed easier. I
could not see where I would initialise the accumulators for each agent.
With the first sequence, the agent first sets all accumulators to zero,
then loops through all linked bookings.
If instead I'm looping through all bookings adding them to their
respective agents, when do the agents get initialised? I think I would
need a prior loop though all the agents to zeroise them, in which case
this method becomes more trouble that the other. Did you see this
differently?
The absence of any real speed improvement in my earlier switch from
loading selected rows from an entity to reading through the members of
a one-to-many relationship exposes an invalid assumption in my original
understanding. I had been thinking that fetching from the Booking
entity meant reading the disk, whereas following the relationship from
the Agent to each Booking would somehow not need disk access. I wasn't
really thinking this through. Of course even though I don't explicitly
fetch from the Booking table, asking for
agent.bookings().objectAtIndex(i) will have to read the disk at some
point.
What I am seeing is that the transaction takes way too long the first
time, but works very quickly if I repeat it immediately.
I initiate the transaction from a small form that contains a start
month, finish month and a submit button.
I click submit and wait. After a while Safari reports no response.
Some log messages in the program show that Safari took just over two
minutes to perform the transaction, but before it got to the end it
reports "broken pipe"
Click submit again and the report is returned in under three seconds.
I presume that what is happening here is the first attempt has to read
from the disk, while the second has everything in memory. The
difference between these two situations completely overwhelms any
difference in the logical efficiency of various processing strategies.
Not to mention the fact that the
bindings might get synchronized (calculated) multiple times (not for
the
first display).
Now this statement hints at something that has always puzzled me about
WebObjects.
If I put a log message into the setAgent() method at the top of this
mail, and another in the action method bound to the submit button I see
that the program does this:
setAgent(1)
setAgent(2)
setAgent(3)
..... and so on
submit()
setAgent(1)
setAgent(2)
setAgent(3)
..... and so on
Why is the process of looking through agentList, setting each agent,
performed twice, once BEFORE the action method and again after it? I
assume this is what you mean by "synchronized (calculated) multiple
times", but I have not understood why this happens. The program wrote
the agent values to the page, but they are not inside a form, so how
and why would it be getting them back? As you point out, this can
result in calculations being performed twice. In this particular case
I have put code into the setAgent() method to detect when it is being
called before the submit() method and bypass the unnecessary
calculation, but why is setAgent() being called? What is calling it?
This makes binding to a method returning a value, as opposed to binding
to an instance variable, a very bad strategy.
Denis
Denis Stanton
email@hidden
Home: +64 9 533 0391
mobile: +64 21 1433622
_______________________________________________
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.