[wx-dev] Re: Idle handling under wxMSW and wxGTK

1 view
Skip to first unread message

John Skiff

unread,
Jul 25, 2002, 11:45:02 AM7/25/02
to wx-...@lists.wxwindows.org
Vadim Zeitlin wrote:

> On Tue, 23 Jul 2002 18:14:16 -0400 John Skiff <jo...@dgi.com> wrote:
>
> JS> I discovered that in a large application, idle handling becomes too slow
> JS> to be usable. I'm using the CVS from June 12. (I submitted bug 583484
> JS> on this).
>
> Yes, this is a known problem and there have been a few discussions on
> wx-dev about (search for "idle" && "performance" and you should find them
> in the archives).


I found a lot of discussion on this topic, especially in April. It
appeared to me that a couple of approaches which sounded promising were
presented but then the discussion stopped. I would like to propose a
simple solution to part of the problem. It doesn't address the overall
problem but it should work fine for simple background processing such as
Pete needs to do. I currently have a large application which is no
longer usable because the number of windows has slowed idle processing
down too much.

The code changes below are for wxMSW but I'd be happy to prepare a patch
for all of the platforms.

To wxIdleEvent add:

class WXDLLEXPORT wxIdleEvent : public wxEvent
public:
void TopWindowRequestMore((bool needMore = TRUE)
{ m_requestMore = needMore;
m_topWindogwOnly = TRUE;}
bool TopWindowOnly() const { return m_topWindowOnly; }

protected:
bool m_topWindowOnly;


Change app.cpp:

bool wxApp::SendIdleEvents()
{
int needMore = FALSE;

wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
while (node)
{
wxWindow* win = node->GetData();
if ((needMore = SendIdleEvents(win)) == -1)
return TRUE;

node = node->GetNext();
}

return needMore;
}

// Send idle event to window and all subwindows
int wxApp::SendIdleEvents(wxWindow* win)
{
bool needMore = FALSE;

wxIdleEvent event;
event.SetEventObject(win);
win->GetEventHandler()->ProcessEvent(event);

if (event.MoreRequested())
needMore = TRUE;

if (event.TopWindowOnly())
return needMore ? -1 : 0;

wxNode* node = win->GetChildren().First();
while (node)
{
wxWindow* win = (wxWindow*) node->Data();
if (SendIdleEvents(win))
needMore = TRUE;

node = node->Next();
}
return needMore;
}

The above involves changes to only a few lines of code and it will make
background processing work.

What do you think?

Thanks,
john

PS: RequestMore has an argument:
void RequestMore(bool needMore = TRUE)

Is FALSE ever passed to RequestMore? If not then I would amend my
proposal. Instead adding the new member TopWindowRequestMore the
argument to RequestMore could be used to say whether idle requests
should go to all windows or to just the top one.


Dave Webster

unread,
Jul 26, 2002, 3:25:02 AM7/26/02
to wx-...@lists.wxwindows.org
Something like this could make asynch socket operations under wxOS2 a little
"cleaner". Stefan, you did the socket stuff for wxOS2, is that so?

I know I failed miserably when I tried to add in our internal, generic
Asynch functor mechanism a while back and tried to depend on idle processing
to dispatch AO's. Kept losing ftor context. I think that was similar to
the socket problems as well. Maybe something like this would help?

-----Original Message-----
From: John Skiff [mailto:jo...@dgi.com]
Sent: Friday, July 26, 2002 9:04 AM
To: wx-...@lists.wxwindows.org
Subject: Re: [wx-dev] Re[2]: Idle handling under wxMSW and wxGTK


Vadim Zeitlin wrote:
>
> As I'd already written, this simply can't work. There are
> (child)windows which must receive the idle events to work correctly.

Yes, I realized that it wouldn't work right after I pressed the Send
button:(

> We need a way to selectively send the idle events only to the windows
> which requested it, there is no way around it.

This will be great. However I'm trying to come up with something that
can make it into 2.3.3. Its really important to me and I can create
the patch.

Its obvious that a solution separate from idle events is required for
now. I think that what we need is a wxBackgroundProcessEvent. What
about something along the lines of following in event.h, app.cpp under
wxMSW?

-----event.h-----------
class WXDLLEXPORT wxBackgroundProcessEvent : public wxEvent
{
public:
wxBackgroundProcessEvent()
: wxEvent(0, wxEVT_BACKGROUND_PROCESS)
{ }
virtual wxEvent *Clone() const {
return new wxBackgroundProcessEvent(*this); }
private:
DECLARE_DYNAMIC_CLASS(wxBackgroundProcessEvent)
};
----app.cpp-----------
static bool backgroundNeedsMore = FALSE;
static bool BackgroundMoreRequested() { return backgroundNeedsMore; }
void wxBackgroundRequestMore(bool needMore = TRUE)
{ backgroundNeedsMore = needMore; }

static bool ProcessBackground()
{
bool needMore = FALSE;

if (BackgroundMoreRequested()) {


wxWindowList::Node* node = wxTopLevelWindows.GetFirst();

if (node) {


wxWindow* win = node->GetData();

wxBackgroundProcessEvent event;
event.SetEventObject(win);
win->GetEventHandler()->ProcessEvent(event);
}
needMore = BackgroundMoreRequested();
}
return needMore;
}
int wxApp::MainLoop()
{
m_keepGoing = TRUE;

while ( m_keepGoing )
{
while ( !Pending() && ProcessIdle() && ProcessBackground())
;

// a message came or no more idle processing to do
DoMessage();
}

return s_currentMsg.wParam;
}

In the above I assume that the application will call
wxBackgroundRequestMore() to tell the library to send a
wxBackgroundProcessEvent. Then the event handler will call
wxBackgroundRequestMore(FALSE) if its done or
wxBackgroundRequestMore(TRUE) if it isn't done.

Or we could mimic the idle event code and require that a
wxBackgroundProcessEvent event be sent to determine if more has been
requested.

How about it?

Thanks,
john

_______________________________________________
wx-dev mailing list
wx-...@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wx-dev

Vaclav Slavik

unread,
Jul 27, 2002, 12:35:26 AM7/27/02
to wx-...@lists.wxwindows.org
Hi,

Julian Smart wrote:
> How does this sound?

Frankly, I dislike the virtual methods part. We use events tables
everywhere and it should stay so, for the sake of API consistency
(it's much easier to learn a consistent API than a Big Mess where
something is tables-based and something virtual funtions-based...).

Aside from this aestetical point of view, your approach still doesn't
(as I understood it) solve the problem (which is that update UI
events don't scale) -- it helps a bit by *postponing* it (when low
priority is used for UpdateUI events) but it won't prevent the
overload. I don't think virtual methods are *that* faster, either (if
fact, I believe the difference is marginal).

I would very much prefer the solution proposed by Vadim last time this
was discussed at wx-dev (Vadim's post digged from my archive is
bellow). It is very simple solution (nice API and only small changes
to it), is 100% backward compatible (you have to enable new idle
events model explicitly) and *fixes* the problem once for all (you
have to register handlers interested in idle events which means there
is _no_ overhead at all).

The proposal is bellow -- what do you think about it?

Regards,
Vaclav


---------- FWD ----------

Subject: Re[6]: [wx-dev] wxGTK Idle Processing (was wxGTK Refresh
fixed (for me))
Date: Fri, 19 Apr 2002 00:34:39 +0200 (Romance Daylight Time)
From: Vadim Zeitlin <zei...@dptmaths.ens-cachan.fr>
To: wx-...@lists.wxwindows.org

On Thu, 18 Apr 2002 16:50:58 +0200 Robert Roebling
<rob...@roebling.de> wrote:

RR> Peter J. Stieber wrote:
RR>
RR> > I feel it's a hack to intermingle user idle event
RR> > processing (which may have nothing to do with the
RR> > GUI) and idle framework GUI processing.
RR>
RR> I tend to agree.

I tend to not disagree although I also understand that it could have
seemed like a good idea back when it was done - it was difficult to
foresee all the problems this would result in in advance.

RR> For that very reason, I already have
RR> introduced wxWindow::OnInternalIdle() for both wxGTK
RR> and wxX11 on the window level, although not yet on
RR> the app level. I can move the window updating in
RR> wxApp to some internal function, too.

This still won't solve the problem of the controls doing redrawing
in the idle time - how can this work if the user intercepts the idle
events?

RR> If we agree that the current idle handling really
RR> is a time consuming process that needs changing,
RR> then we might consider to make idle events an
RR> exception to the event rule and give it a different
RR> API (just virtual methods which are faster than
RR> events).

This is still not the good solution: the time taken by idle events
processing would still be proportional to the total number of windows
in the program even if none of them needs them. The only real
solution to the performance problems would be to require all windows
interested in getting the idle events to register themselves. And
then, BTW, we wouldn't need any virtual functions but could still
use the events.

What about this draft proposal: let's have 2 modes between which you
could toggle by calling wxApp::SetIdleModel(). The first one is what
we do now, it's inefficient but simple to understand and 100%
backwards compatible by definition. In the 2nd mode, the idle events
are not sent by default. You have to call
wxApp::AddIdleHandler(this) or something like that to start getting
them. And there should also be wxApp::RemoveIdleHandler(), of
course. We could use the same wxIdleEvent for such explicit idle
handlers or call a virtual function or send them some
wxExplicitIdleEvent - personally I think that simply sending
wxIdleEvent would do.

The important thing is that we keep backwards compatibility but
provide a way to get rid of the performance problems when needed.

What do you think?
VZ


Robert Roebling

unread,
Jul 27, 2002, 4:00:02 AM7/27/02
to wxWindows developers list
> I don't think virtual methods are *that* faster, either (if
> fact, I believe the difference is marginal).

It would be nice to get some data for this. I myself believe
that virtual methods are a lot faster and that switching
to virtual methods in this case would solve many problems
indeed. It is not API consistent, of course, but I am
afraid that we will have to look for some kind of trade-off
in any case. Better ideas welcome.

Robert

Julian Smart

unread,
Jul 27, 2002, 7:20:02 AM7/27/02
to wx-...@lists.wxwindows.org
At 12:53 27/07/2002 -0400, you wrote:
>What I was proposing was to leave idle handling as it is for 2.3.3 but to
>add a new event which could be used by users who need background
>processing but don't need it for every window. Since the existing idle
>handling would still be in place I don't see how there would be a problem
>with backward compatibility.

But I thought that the existing scheme was inadequate, i.e.
too time-consuming, largely due to sending UI update events. So I
don't see how adding a new event to the existing, creaky
system is going to buy us more efficiency :-)

>Personally I'd be delighted if you implemented what you have proposed.
>IMHO since consensus is so difficult on this somebody is going to have
>implement something or the conversation will die out again like it did in
>April.

Well yes, tempting though it is to go ahead and
implement something, I would probably be shot down
in flames and have to revert it if we didn't have
agreement.

Regards,

Julian
========================================================================
Julian Smart mailto:julian...@btopenworld.com
3 Water Street, Stamford, http://www.anthemion.co.uk
Lincs, U.K., PE9 2NJ +44 (0)1780 765976
Try StoryLines - the fast,
fun fiction structuring tool http://www.storylinescentral.com
========================================================================


Robin Dunn

unread,
Jul 27, 2002, 10:20:02 AM7/27/02
to wx-...@lists.wxwindows.org
> >Perhaps in this case we should do something similar and have two or three
> >solve-the-idle-processing-problem patches put on SF that people can try
out
> >and/or improve upon and then vote on which is the best which is then
checked
> >in to CVS.
>
> Sounds good (if I had a shred of confidence left in my own proposals)
> but isn't it inconvenient for the individual to apply a patch which then
> might have to be reverted? Or can you put the patch into reverse,
> rather than deleting all affected files and doing a cvs update.

There might be a cvs command to do it, but with tools like WinCVS (I think)
or pcl-cvs in emacs it's fairly easy to find all files marked as modified
and revert them.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!


Stefan Csomor

unread,
Jul 28, 2002, 1:15:02 AM7/28/02
to wx-...@lists.wxwindows.org
Hi

I also like the proposed extension, one alternative came to my mind, but
I have not yet fully thought the consequences through :

If we had on the level of an event handler a kind of compressed
event-map cached, so that we would know whether an object responds to an
event at all (either itself or any of its ancestors) ...

... wouldn't this offer a transparent way for optimizations in the code
? As soon as a dynamic event handler would be plugged or unplugged we
would invalidate the cache on the object

Best

STefan

> -----Original Message-----
> From: wx-dev...@lists.wxwindows.org
> [mailto:wx-dev...@lists.wxwindows.org] On Behalf Of Vaclav Slavik
> Sent: Samstag, 27. Juli 2002 13:27
> To: wx-...@lists.wxwindows.org
> Subject: Re: [wx-dev] Re[2]: Idle handling under wxMSW and wxGTK
>
>

> RR> > I feel it's a hack to intermingle user idle event processing
> RR> > (which may have nothing to do with the

Dave Webster

unread,
Jul 29, 2002, 2:15:20 AM7/29/02
to wx-...@lists.wxwindows.org
I believe this is something pretty important after thinking about it for
while. I can see where there could be a lot of benefit in separating out
framework idle processing from application idle processing. In fact, if
many of the applications we have had been developed using wxWindows, I think
this ability would have been essential as we do a great deal of background
work in app idle time processing like dispatching our own async operation
ftors and such and I have never really figured out how to mesh that type of
processing cleanly with wxWindows.

-----Original Message-----
From: Peter J. Stieber [mailto:deve...@toyon.com]
Sent: Saturday, July 27, 2002 11:57 AM
To: wx-...@lists.wxwindows.org
Subject: Re: [wx-dev] Re[2]: Idle handling under wxMSW and wxGTK


All,

Very happy to see this issue taken-up again. I have been the naive solution
suggestor concerning this issue multiple times in the past. I understand it
is very difficult and backward compatibiity is a must. On the other hand, I
still have to work around the problem (different app code between wxMSW and
wxGTK). The people I convinced to use wxWindows at my place are starting to
wonder. I've been talking about the "idle processing problem" since Feb.
(maybe earlier, but I can't remember) at work and they are wondering why
there hasn't been a solution. If they only understood the tremendous amount
of "other" issues. Oh well, I understand.

I still see benefit in separating user idle processing (which might not have
anything to do with the GUI) and framework GUI idle processing. How about a
new event that is handled by OnBackgound, like John suggested. Internally it
is generated by the same code that sends the OnIdle event, but there is one
new API function (not sure where it would belong) that determines the ratio
of Background events to "good old" Idle events. This new Background event
would have to be "registered" as in Vadim's proposal, but by the application
code. If it isn't registered, everything works as it does now. If it is, the
default frequency of the event is equal to that of OnIdle. The new API
function would take an interger arg that would indicate the calling ratio

void wxBackgroundRation(int Ratio);

Ratio
-10 -> generate 1 background event for every 10 idle events
-1, or 1 -> the default, 1 background for each idle
10 -> generate 1 idle event for every 10 background events
0 -> background never called

I'm sure there are more holes in this than a sieve, but I want to keep the
discussion going.

I've said it before, but I'll mention it again, I would be very willing to
be a tester for any trial solution.

BTW, thanks for all of your work on wxWindows. Vadim answers more posts on
this list than I even have time to read.

Pete Stieber

Reply all
Reply to author
Forward
0 new messages