Developer forums (C::B DEVELOPMENT STRICTLY!) > CodeCompletion redesign

CodeCompletion slow on some machine

(1/5) > >>

seb_seb0:
I have a slowness problem with CodeCompletion.
The exact problem is as follow:
  - the problem appear only on 1 machine (Windows XP 32 bits 2007 SP3, CB SVN build 7925, at work)
    It does not appear on my own laptop (Windows 7 64 bits,  CB SVN build 7925). Both config have approximately same hardware configuration (1 year laptop, powerful enough for running CAD softwares).

  - slow loading of workspace. I have a workspace consisting of 23 projects. Each projects has between 10 and 550 files (total : 1600 files approximately, counting .h files)
    On my work computer, the project loads 10 times slower when CodeCompletion is activated (measured : 1 minute against 10 minutes roughly)

  - when editing a project file, the IDE freezes for 1 to 5 minutes (again, only on the work computer, with XP). What I mean with editing is : open a file (new tab in the wxAUI notebook), and activate it by clicking with the mouse. This is the most annoying bug.

  - This problem did not happen in the Debugger Branch, until the recent merge with trunk.

I have tryied to debug the CodeCompletion plugin using instructions on the Wiki (Ctrl + Shift + "debug SmartSense"), but it did not help a lot (or I do not know what to look for in the log).

  I am willing to compile a special version of the CodeCompletion plugin and try it at work, to know where is the problem (and possibly correct it). Basically, I want to add some debugging message and timers information in the debug log.

  Can someone help me in identifying the hot spots in the plugin ? Where should I start to look for possible candidates ?

Seb

MortenMacFly:

--- Quote from: seb_seb0 on April 10, 2012, 09:34:53 pm ---Can someone help me in identifying the hot spots in the plugin ? Where should I start to look for possible candidates ?

--- End quote ---
Can you first try what happens if you disable the ToDo list plugin (yes: ToDo)?

seb_seb0:

--- Quote from: MortenMacFly on April 10, 2012, 09:41:28 pm ---
--- Quote from: seb_seb0 on April 10, 2012, 09:34:53 pm ---Can someone help me in identifying the hot spots in the plugin ? Where should I start to look for possible candidates ?

--- End quote ---
Can you first try what happens if you disable the ToDo list plugin (yes: ToDo)?

--- End quote ---

I have tried that, and unfortunately it did not help.
I have tried to measure the code speed on my laptop at work : I have found a few solutions, although it is not perfect.

BUG 1 : loading a workspace is 10 times slower on Win XP than on Win 7 (laptop on WinXP is an Intel Core I7, laptop on Win7 64 is an Intel Core I5)
  => most of the time is spent in the method NativeParser::AddCompilerDirs.

More specifically : it seems to be in these following pieces of code:


--- Code: ---// get targets include dirs
    for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
    {
        ProjectBuildTarget* target = project->GetBuildTarget(i);
        if (target && target->SupportsCurrentPlatform())
        {
            if (compiler)
            {
                // post-processed search dirs (from build scripts)
                for (unsigned int ti = 0; ti < compiler->GetCompilerSearchDirs(target).GetCount(); ++ti)
                {
                    wxString out = compiler->GetCompilerSearchDirs(target)[ti];
                    wxFileName dir(out);
                    if (NormalizePath(dir, base))
                    {
                        parser->AddIncludeDir(dir.GetFullPath());
                        TRACE(_T("AddCompilerDirs() : Adding compiler target dir to parser: ") + dir.GetFullPath());
                    }
                    else
                        CCLogger::Get()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"), out.wx_str(), base.wx_str()));
                }
            }

            // apply target vars
//            target->GetCustomVars().ApplyVarsToEnvironment();
            for (unsigned int ti = 0; ti < target->GetIncludeDirs().GetCount(); ++ti)
            {
                wxString out = target->GetIncludeDirs()[ti];
//                Manager::Get()->GetMacrosManager()->ReplaceMacros(out);
                wxFileName dir(out);
                if (NormalizePath(dir, base))
                {
                    parser->AddIncludeDir(dir.GetFullPath());
                    TRACE(_T("AddCompilerDirs() : Adding target dir to parser: ") + dir.GetFullPath());
                }
                else
                    CCLogger::Get()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"), out.wx_str(), base.wx_str()));
            }
            // get the compiler
            wxString CompilerIndex = target->GetCompilerID();
            Compiler* tgtCompiler = CompilerFactory::GetCompiler(CompilerIndex);
            if (tgtCompiler)
            {
                Compilers[nCompilers] = tgtCompiler;
                ++nCompilers;
            }
        } // if (target)
    } // end loop over the targets

    // add compiler include dirs
    for (int idxCompiler = 0; idxCompiler < nCompilers; ++idxCompiler)
    {
        const wxArrayString& dirs = (Compilers[idxCompiler])->GetIncludeDirs();
        for (unsigned int i = 0; i < dirs.GetCount(); ++i)
        {
//            CCLogger::Get()->Log(mltDevDebug, "Adding %s", dirs[i].c_str());
            wxString out = dirs[i];
            Manager::Get()->GetMacrosManager()->ReplaceMacros(out);
            wxFileName dir(out);
            if (NormalizePath(dir,base))
            {
                parser->AddIncludeDir(dir.GetFullPath());
                TRACE(_T("AddCompilerDirs() : Adding compiler dir to parser: ") + dir.GetFullPath());
            }
            else
                CCLogger::Get()->DebugLog(F(_T("Error normalizing path: '%s' from '%s'"), out.wx_str(), base.wx_str()));
        }

        // find out which compiler, if gnu, do the special trick
        // to find it's internal include paths
        // but do only once per C::B session, thus cache for later calls
        wxString CompilerID = (Compilers[idxCompiler])->GetID();
        if (CompilerID.Contains(_T("gcc")))
            AddGCCCompilerDirs(Compilers[idxCompiler], parser);
    } // end of while loop over the found compilers

--- End code ---

(code for finding the compiler and target include directories, and compute full-path from that).


So I have optimized a bit this method :
    1 - cache loop boundaries (no need to call each loop GetCount()). I know it is probably not significant, but just for testing
    2 - Optimize ParserBase::AddIncludeDir : there is a call here to wxArrayString::Index, which is linear (O(n)). I have added a HashSet for string (available in wxWidgets)
    3 - clean up the code : there is 3 times the same code to do: fetch include dir, do macro expansion, normalize the path, add to include dir list. I have moved this code inside a new method ParserBase::AddIncludeDirFast, and commented out the previous code
    4 - there is probably some other optimisations to perform : there is a lot of wxString copy overall.

I attach a patch with :
    - the modifications discussed above
    - some additional debugging code in NativeParser.cpp and codecompletion.cpp (can be deactivated).
   

Applying the patch above helped a lot... at first. After 1 hour, the slow behaviour resumed, so there must be another bottleneck somewhere.


BUG 2 : same freezing behaviour, but I can reproduce it at will now. Use case is as follow:
    - large workspace, with several projects
    - project A is active
    - open a file from another project (not from the active project) => freeze for 2 to 6 minutes observed.

Debug logs pointed out to NativeParser::AddCompilerDirs again. The patch above solved this problem as well - for 1 hour...

I am sorry if I could not find out more - after a while, I had to resume what I should have been doing at work : working. I will try again when possible

Regards,

Seb

ollydbg:
I see you add some profile timers, that's nice, I will test it. I sometimes experience that lag problem I'm editing, about 2-3 seconds, at that time, the whole editor locks.

BTW:
There are many linear searches in function like:

--- Code: ---cbProject* NativeParser::GetProjectByFilename(const wxString& filename)

--- End code ---

seb_seb0:

--- Quote from: ollydbg on April 12, 2012, 04:12:53 am ---I see you add some profile timers, that's nice, I will test it. I sometimes experience that lag problem I'm editing, about 2-3 seconds, at that time, the whole editor locks.

BTW:
There are many linear searches in function like:

--- Code: ---cbProject* NativeParser::GetProjectByFilename(const wxString& filename)

--- End code ---


--- End quote ---

You are right - I have just tried what is obvious first.

Today, I have done more tests :
  - keep only CodeCompletion and Compiler plugin (physical delete of all the other plugins) => the lag still persists => this is not due to some complex interaction with another plugin
  - I have tried to compile the codecompletion code from the last debugger branch on the last trunk nightly => I still get the block
     The same code on the Debugger branch does not block at all (7 seconds to open my workspace, agains 140 seconds with the last nightly + same code-completion code) => there is a deep change somewhere in the code::blocks codebase which provokes the slow behaviour
  - why does it blocks on Win XP and not on Win 7 ? This is perhaps thread related, but it is a very wild guess.
  - when I omit to normalize the path of the include directories (no call to wxFileName::Normalize in NativeParser::AddCompilerDirs), I do not get the blocking behaviour. (this can perhaps help to diagnose the cause of the problem).
  - all the time is spent in the method NativeParser::AddCompilerDirs (140 seconds on 141). Skipping this method resolves the blocking behaviour (but less includes directories are parsed, so there are less risk of blocking)
  - same blocking behaviour happens with other workspaces (CodeBlocks contrib plugins).

I will try to compile the code-completion plugin with older code::blocks version, to see if the blocking behaviour has been triggered by a specific version. Be patient, because it will take some time...

Truth to be said, I am a bit lost currently, because I do not know how the plugin works. I can read the source, of course, but it takes time. Currently, I work with the last debugger nightly.

Seb

Navigation

[0] Message Index

[#] Next page

Go to full version