Author Topic: Making the workspace / project loading asynchronous?  (Read 7910 times)

Offline rickg22

  • Lives here!
  • ****
  • Posts: 2283
Making the workspace / project loading asynchronous?
« on: September 05, 2005, 07:19:14 am »
Yiannis, I was looking at the code and I have this proposal for post-1.0...

What needs to be done so we can make the workspace / project loading asynchronous?

i.e. instead of returning a value of success / failure, make it trigger some events like OnWorkspaceLoaded and OnWorkspaceFailedLoading ?

I say this because workspace / project loading is one of the slowest routines of C::B, and this was one of the reasons for wanting to insert wxYield's in there.

So the current model is more or less like this:

(Synchronous)
Load Workspace -> Lots a stuff with lots of wxYield's in the middle -> Return value

I want to change it to:

(Asynchronous)
Load Workspace -> Idle Event handling for workspace / prj loading -> Success / Failure events

In other words, I want to make explicit the "interruptions" (event handling) that happen in the middle of workspace / project loading, and give more order to it. This would get us rid of the wxYield's and their consequences like having to insert SANITY_CHECK's all over the place in the workspace loading areas.

The part that looks difficult is that I'd have to modify the *workspaceloaders... any ideas?


Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Making the workspace / project loading asynchronous?
« Reply #1 on: September 05, 2005, 09:46:05 am »
I don't agree. It's overcomplicating things, not to mention that it is asking for trouble...
What problems do you have when loading workspaces?
Be patient!
This bug will be fixed soon...

Offline rickg22

  • Lives here!
  • ****
  • Posts: 2283
Re: Making the workspace / project loading asynchronous?
« Reply #2 on: September 05, 2005, 09:00:09 pm »
I just want to get rid of the wxYield's. If you disable them ("improved stability" under "environment options", "tweaks"), the interface becomes unresponsive while loading the project. But keeping the wxYields in the message manager is asking for trouble, see http://forums.codeblocks.org/index.php/topic,726.0.html and http://www.wxwidgets.org/manuals/2.4.2/wx30.htm#wxappyield. My point is that if we keep having those wxYields, we'll have to deal with unexpected crashes on EVERY version.

So, how about an intermediate solution, like asynchronous loading of the layout for projects?

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Making the workspace / project loading asynchronous?
« Reply #3 on: September 05, 2005, 09:37:16 pm »
Can you define "asynchronous"?
If you 're thinking of threads, you can forget it ;) The sdk is *not* thread-safe...

I believe a progress dialog should be enough clue for the user of what's going on and you can remove the wxYields too. Every other solution is just too much, at least for now. Just my 2c.
Be patient!
This bug will be fixed soon...

Offline rickg22

  • Lives here!
  • ****
  • Posts: 2283
Re: Making the workspace / project loading asynchronous?
« Reply #4 on: September 05, 2005, 10:54:18 pm »
Can you define "asynchronous"?

Asynchronous: Not synchronous. i.e. it would run in the background. My plan was not to use threads, but background processing with events.

I tested this idea in my PC when you were gone, this is why I added the OnIdleEvent handler for projectmanager.cpp. What I did for my test was popping up a messagebox every N idle cycles. It appeared every  3 or 4 seconds. So "yep", that could work :) The idle handler would check if a project's layout was being loaded, and open the files one by one.

My reason for using the Idle event was because using command events would freeze the GUI. The Idle events are only handled after the window messages are processed. I thought about it for a lot time, and it seems (to me at least) an elegant solution to the "GUI freezing" problem.

My original idea was to do the project loading in the idle handler, but i hadn't realized that this would have to chain to the workspace loading.

However, I think that the Layout loading (opening of files) can be done this way. We know what operations to perform, and the timing isn't critical. (Maybe the project tree generating could be done this way, but that would require further analysis. I'd rather focus on the layout loading for now).

So, what do you think?

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Making the workspace / project loading asynchronous?
« Reply #5 on: September 05, 2005, 11:23:16 pm »
Just so people watching this topic know, after a private discussion between me and Rick, we decided this will have to wait until after 1.0 is out.
Be patient!
This bug will be fixed soon...

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Making the workspace / project loading asynchronous?
« Reply #6 on: October 03, 2005, 03:49:38 pm »
Hmm... I think Yiannis is right here.

Although I love asynchronous execution, and it is a good idea, I don't think it is helpful in this particular case. The benefits of asynchronous operations are that although everything is in fact slower, the user perceives differently as he can work on while things happen in the background. This is not the case here.
You cannot start working on a project before it is fully loaded, so there is no benefit unless you work on a different project that is already open. However, you do open a project because you want to work on that one, not on another.
Thus, asynchronous loading even makes the actual problem worse (and it adds to complexity, and pushes even more messages onto the already busy message queue, too).

Maybe optimizing cbProject::Open is worth a consideration. One of the nice things in Code::Blocks is that everything is coded "the very safe, very obvious way". Clarity rather than maximum speed. This is a good thing really, it works very well and possibly catches problems that one did not think about in the first place. Also, it is very easy to follow the code and to see what is going on. Plus, speed does not matter 99% of the time, at all. Every PC can handle a few extra calls and a few indirections without any noticeable penalty.
With cbProject::Open, things are different, however. Loading projects is noticeable, even painful sometimes. So maybe here, doing a few speed optimisations might really be advantageous.

While opening a large project (~700 files), Code::Blocks spends amazing amounts of CPU time in CalculateCommonTopLevelPath (and in various wxFileName functions called from other places, and wxString::ConcatSelf). Surprisingly, the many tinyxml function calls sum up to only about 2.5% total CPU time. I would have expected a lot more. Tinyxml is really awesome.
One could try to do some more result caching in a few places to avoid function calls and double-triple-quadruple indirections, and might consider not calling SetModified(false) which is a lot more expensive than it sounds (and not necessary).

Many wxWindows functions are a lot more expensive than they look, too. For example, wxFileName::GetPathSeparator() looks quite innocent. That function is probably inlined and returns a reference to a const wxString or something, right? You wish.
In fact it is a non-inline static function which calls another non-inline function that goes through a non-const switch statement (and calls yet another function for the switch argument), creates a temporary wxString object (default constructor), explicitely assigns a constant string and uses operator[] on the temporary.
When you concatenate the resulting  wxChar to a wxString (the typical thing to do), another temporary is implicitely created. Clearly, you don't want to do that a few thousand times in a row.
The other wxFileName functions are still a lot more expensive (many of them in fact call GetPathSeparator() one or several times), so if one can only save one or two calls for every file opened, a lot could be gained.

Maybe it is possible to make project loading 2-3 times faster by doing some magic here and some magic there. Then nobody would bother about project loading any more at all. Just my thoughts.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."