Why not to use direct display updates
Why not to use direct display updates
- Subject: Why not to use direct display updates
- From: Marcel Weiher <email@hidden>
- Date: Tue, 11 Dec 2001 01:10:16 +0100
On Montag, Dezember 10, 2001, at 09:08 Uhr, jgo wrote:
1. Incorrect reasoning
Using -setNeedsDisplay: has nothing to do with spirits from another
plane, but follows the standard event-response-update cycle that Cocoa
implements. With Cocoa, -setNeedsDisplay: is the default method,
-display the exception.
Furthermore, doing the display immediately will not actually show
anything on screen unless you also flush the window and/or the context,
but this will cause performance problems because the event loop will
likely flush the window again. So using -display is neither simpler,
nor more direct without even more extra work.
2. Fighting the framework and doing too much work
Even though you did a display update yourself using -display
during event-handling, the Cocoa event loop will still do
its update-processing afterwards. So your application will
be doing extra, unecessary work. You might think that using
-display is somehow 'more direct', but it isn't.
If the needsDisplay characteristic has not been set, then the event
processing should not eat up time doing a display
Correct. It won't eat up time doing a display, but it will eat up time
determining that it doesn't need to do a display.
.. unless the system has decided to set it for one reason or another.
Exactly. With Cocoa + Aqua, there may be elements on the display that
need updating that you don't (want to/need to) know about. So your
assumption of only drawing once may be wrong without you even knowing
about it. Furthermore, assumptions about your environment always make
your code more brittle. It is always better if your code works well
without such assumptions. The built-in update logic does, direct-update
does not.
So, there's no inefficiency, no lost cycles.
There will be small inefficiency in the best case, and a LOT of
inefficency in a fairly likely worst case.
If I'm doing extraneous updates, then that suggests need for
reworking my code.
Exactly. There are situations where your way suggests a need for
reworking your code.
If you use the provided logic, It Just Works (TM) no matter what.
That is what makes your way brittle.
If the framework or OS decides to do an extraneous update, then that is
where the finger should be pointed at WRT inefficiencies.
It is not doing extraneous updates. The code to check what has to be
updated has to run, and it will run anyhow. It may be trivial, it may
not be. You don't know.
Of course,after a series of displays it should force the pixels
on-screen,
Nope. It should force the pixels on-screen before it goes to wait for
another event, or if explicitly told so because the app-logic knows that
it won't be waiting for an event for a significant amount of time.
so, yes, I was simplifying to the same degree as the prior
post in the thread.
3. Fragile code / modularity
As you yourself pointed out, waiting for the automatic update
cycle is better when several updates need to be performed.
This means that your direct-display update code makes an
assumption about its environment (no other updates) and will
need to be changed if that assumption ever changes.
That's not what I wrote. What I wrote was that the update should
occur at an appropriate point after a series of updates.
Doesn't make a difference to what I am saying.
Since the
time when the "automatic update cycle" does it is arbitrary &
unknown,
This is completely untrue. The automatic update cycle is deterministic
and occurs at a well-known time that is appropriate most of the time.
these 2 times do not usually coincide.
Quite the contrary, they almost always coincide. Can you give examples
where they do not coincide?
-setNeedsDisplay: on the other hand works just as well as a single
update as it does in a series of updates.
No, it does not do it "just as well as a [specific] update" because
it does it at its whim,
It does not do it at its 'whim', it does it after the current event has
been dispatched and before waiting for the next event.
Except for the case of very long-running event processing, I can't think
of many cases where this isn't the appropriate time. As a matter of
fact, a well-behaved Cocoa app should not have long-running event
processing, but rather dispatch long running processes to a background
task/thread or timer, so quite possibly the automatic update is always
appropriate.
(Back in the days of '040 hardware, it was common to do your own event
dispatching for interactive operations such as dragging etc., but I
don't think that is still necessary)
not "mine", which, hopefully, coincides with the users'.
Well, the automatic update cycle is finely tuned to coincide exactly
with the users' whim. Is yours?
I don't quite see the rationale for making your code more brittle
without any gain, especially since you don't necessarily have full
control over what other updates may be occuring.
Ahh, now here's a point to explore. In what way is one way of
handling this any more or less "brittle" than another.
I've explained this above, though apparently not well enough, because it
seems it was too easy to get distracted by completely irrelevant side
issues. I will explain again, using your explanation as a starting
point:
Since
a redraw & display are a single transaction, it makes sense for
it to be in a nice, neat, encapsulated unit
That is exactly what it is not. It *may* be a single 'transaction' now,
but if it is modular code, that same code may be reused in another
context where it is part of a series of updates.
that doesn't rely
on some far-flung process to be triggered by a stored flag.
The process *is* triggered by a flag, but it is not 'far-flung'. It is
very simple the standard Cocoa display update mechanism. If you have
problems with it, I recommend reviewing the relevant NSView
documentation. NSViews handle drawing in their -drawRect: method.
Views are simply supposed to be able to redraw themselves, no matter
when and where.
What you want to do runs counter to the standard mechanisms. Cocoa is
flexible enough to accomodate you in your wish, but your code will
likely (a) contain redundancies (b) be inefficient and (c) hard to
understand, because it doesn't use what is already there. The only
reason you have given for this so far is your "whim". Once again, you
are free to be whimsical and go against/ignore the framework, and Cocoa
is accomodating enough.
My point is just that this is not good advice for Cocoa programming.
4. Performance
As I've pointed out, your solution will suffer from inferior
performance. -display needs to do significant processing to
set up the view hierarchy for drawing, focusing on each view
in the view-stack in turn. This additional overhead...
It's not "overhead" because it's something that gets done no matter
which of the proposed strategies is used.
It *is* overhead no matter what. The question is wether the overhead is
incured once or several times per update-cycle. The standard mechanism
ensures it is only incured once. You want to introduce extra code that
also introduces the chance of incuring this overhead more than once
without any discernible benefit. This is not to say that there may not
be good reasons to use such a strategy in specific cases, but no such
reason exists for the general case.
Anyway, I think that most of the points have now been sufficiently
covered, so there is no realy need to continue this discussion.
Marcel
--
Marcel Weiher Metaobject Software Technologies
email@hidden www.metaobject.com
Metaprogramming for the Graphic Arts. HOM, IDEAs, MetaAd etc.