News:

Accounts with zero posts and zero activity during the last months will be deleted periodically to fight SPAM!

Main Menu

Compilation much slower under Linux than under Windows

Started by JThedering, August 26, 2006, 03:40:30 PM

Previous topic - Next topic

JThedering

I noticed it for a long time, but now I'd like to do something about it:
When compiling a project in C::B under Linux, the compilation is much slower(in my example project ~15 s) as when using a makefile to do the same steps (~2.5 s).
This problem doesn't exist on Windows, there C::B is equally fast.

I could make it faster by increasing the process count to the amount of source files in Settings->Compiler&Debugger->Other, but it's still not as fast (~ 4 s) because the linking step has to wait until the compiler steps are finished.

I could reduce the problem to the PipedProcess class by testing the behaviour of this class when executing a program. More precisely I could reduce it to the wxExecute call. When I change the wxExecute call to work synchronously, it's as fast as make, but in asynchronous mode, it takes some time until OnTerminate of the PipedProcess is called. (Some values: Compiling a simple hello world C program using "gcc -c test.c" takes 70 ms when doing it synchronously, but 1.4 s asynchronously)

I also made another test: I manually forked the process and called exec, while returning the process id in the parent process, so that it does the same as wxExecute can do. Then I used waitpid frequently (every 10 ms) to check if the process is finished. If I use my simple "version" of wxExecute, it's ~70 ms, but when I create the process with wxExecute, it's slow.

So I ask: Is there a known workaround to this problem or has anyone else any knowledge that could help? Is this a bug in wxWidgets?

Game_Ender

That is odd because to my knowledge in complex projects, like Code::Blocks itself the CB build system is just as fast as make.  When both the autotools and CB project for Code::Blocks are configured with the same build options they should be within about 10% of each other speed wise.  My guess is for small projects, or small files, the overhead of wxExecute is large enough to have a noticeable effect on the build time.

From you findings it seems like you should investigate the wxExectue source code, perhaps you could supply a patch to speed it up on Linux.

thomas

Quote from: JThedering on August 26, 2006, 03:40:30 PMIs this a bug in wxWidgets?
wxExecute is *one* bug. In particular, it is not thread-safe, inefficient, and it can cause re-entrancy even when you do not use multiple threads (runs wxYield() in a spin loop while waiting for the app to terminate).
Unluckily, we're bound to use it, since there is no reasonable alternative (apart from rewriting it from scratch). Using a worker thread that simply calls popen() would be just perfect, this would be a lot more efficient and safe. However, popen  won't do under Windows :(
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

takeshimiya

Maybe someone wants to fix the wxExecute implementation?

In the Unix wxExecute implementation I can read:
Code (cpp) Select
#if wxUSE_THREADS
    // fork() doesn't mix well with POSIX threads: on many systems the program
    // deadlocks or crashes for some reason. Probably our code is buggy and
    // doesn't do something which must be done to allow this to work, but I
    // don't know what yet, so for now just warn the user (this is the least we
    // can do) about it
    wxASSERT_MSG( wxThread::IsMain(),
                    _T("wxExecute() can be called only from the main thread") );
#endif // wxUSE_THREADS


And in the Windows wxExecute implementation I can read:
Code (cpp) Select
#if wxUSE_THREADS
    // for many reasons, the code below breaks down if it's called from another
    // thread -- this could be fixed, but as Unix versions don't support this
    // neither I don't want to waste time on this now
    wxASSERT_MSG( wxThread::IsMain(),
                    _T("wxExecute() can be called only from the main thread") );
#endif // wxUSE_THREADS



Aside, popen:
Code (cpp) Select
// this function replaces the standard popen() one: it launches a process
// asynchronously and allows the caller to get the streams connected to its
// std{in|out|err}
//
// on error NULL is returned, in any case the process object will be
// deleted automatically when the process terminates and should *not* be
// deleted by the caller
static wxProcess *Open(const wxString& cmd, int flags = wxEXEC_ASYNC);



JThedering: if you could fix the above wxExecute implementations, I'm sure the wxWidgets team would greatly appreciate it. :)