Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => CodeCompletion redesign => Topic started by: ollydbg on July 18, 2013, 05:14:50 pm

Title: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 18, 2013, 05:14:50 pm
When loading a project, I see a lot of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages. (You can enable the TRACE of codecompletion.cpp to see them)

I just track down, and I see that: UpdateEditorSyntax(editor); (mostly in CodeCompletion::OnParserEnd()) will cause such message.

Can we avoid them? It's annoying.
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: MortenMacFly on July 18, 2013, 05:28:06 pm
Can we avoid them? It's annoying.
I think not really. It iterates (only!) across the open editors to update the syntax highlighting. If you skip the call to UpdateEditorSyntax() or avoid the event the editors won'T be highlighted correctly. IIRC this is needed for the macro and keyword stuff.

The only thing is not to have too many editors open... :-)
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 18, 2013, 05:28:41 pm
It looks like
Code
void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {

call

Code
	void SetLevel(int line, int level) {
pAccess->SetLevel(line, level);
}

in a loop, so a lot of wxEVT_SCI_MODIFIED was sent. :(
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 18, 2013, 05:30:21 pm
Can we avoid them? It's annoying.
I think not really. It iterates (only!) across the open editors to update the syntax highlighting. If you skip the call to UpdateEditorSyntax() or avoid the event the editors won'T be highlighted correctly. IIRC this is needed for the macro and keyword stuff.

The only thing is not to have too many editors open... :-)
I have just post an analysis result, and found the source of such annoying message. (even only one editor is opened, there are still many messages sent).
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 19, 2013, 04:08:23 am
I track down the source, and I see that the flood of wxEVT_SCI_MODIFIED of messages happen at two time.

1, when loading project files
Code
cbEditor* EditorManager::Open(LoaderBase* fileLdr, const wxString& filename, int /*pos*/, ProjectFile* data)

Each line will be set a new level, and those messages will be sent for each lines
Code
int SCI_METHOD Document::SetLevel(int line, int level) {
int prev = static_cast<LineLevels *>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());
if (prev != level) {
DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
                  LineStart(line), 0, 0, 0, line);
mh.foldLevelNow = level;
mh.foldLevelPrev = prev;
NotifyModified(mh);
}
return prev;
}

2, when parser done, in void CodeCompletion::OnParserEnd(wxCommandEvent& event)
The call statement
Code
UpdateEditorSyntax(editor);
Some code style will change, so there is also some messages of wxEVT_SCI_MODIFIED.

Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 21, 2013, 05:54:48 pm
Ok, I got the correct answer from Scintilla's mail-list, see:
https://groups.google.com/d/msg/scintilla-interest/9Vt8FJFL3CU/aOjLveFw4oAJ
It is by design, but we can filter them(I don't think it is necessary), so leave it as it is. :)
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: Alpha on July 21, 2013, 06:13:36 pm
It is by design, but we can filter them(I don't think it is necessary), so leave it as it is. :)
Could filtering possibly result in a (small) performance gain?
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on July 23, 2013, 09:06:33 am
It is by design, but we can filter them(I don't think it is necessary), so leave it as it is. :)
Could filtering possibly result in a (small) performance gain?
I don't know, maybe we can temporary disable send such message when an editor is created and a file is loaded. To measure performance, there need at least a benchmark test.
Title: Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
Post by: ollydbg on June 08, 2014, 03:28:36 pm
I still see many unwanted event sent, so I did some further debugging.
I found that C::B did try to disable the notifications when an editor was initialized, see the code
Code
bool cbEditor::Open(bool detectEncoding)
{
    if (m_pProjectFile)
    {
        if (!wxFileExists(m_Filename))
            m_pProjectFile->SetFileState(fvsMissing);
        else if (!wxFile::Access(m_Filename.c_str(), wxFile::write)) // readonly
            m_pProjectFile->SetFileState(fvsReadOnly);
    }

    if (!wxFileExists(m_Filename))
        return false;

    // open file
    m_pControl->SetReadOnly(false);

    m_pControl->ClearAll();
    m_pControl->SetModEventMask(0);

    if (!m_pData)
        return false;

    if (!m_pData->m_pFileLoader)
        m_pData->m_pFileLoader = Manager::Get()->GetFileManager()->Load(m_Filename, false);

#ifdef fileload_measuring
    wxStopWatch sw;
#endif
    EncodingDetector enc((wxByte*)m_pData->m_pFileLoader->GetData(), m_pData->m_pFileLoader->GetLength());
    if (detectEncoding)
    {
        m_pData->m_useByteOrderMark    = enc.UsesBOM();
        m_pData->m_byteOrderMarkLength = enc.GetBOMSizeInBytes();
        m_pData->m_encoding            = enc.GetFontEncoding();

        SetEncoding(enc.GetFontEncoding());
        SetUseBom(m_pData->m_byteOrderMarkLength > 0);
    }

    ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("editor"));
#ifdef fileload_measuring
    Manager::Get()->GetLogManager()->DebugLog(F(_T("cbEditor::Open() => Encoding detection and conversion took : %d ms"),(int)sw.Time()));
    sw.Start();
#endif

    m_pControl->InsertText(0, enc.GetWxStr());
    m_pControl->EmptyUndoBuffer(mgr->ReadBool(_T("/margin/use_changebar"), true));
    m_pControl->SetModEventMask(wxSCI_MODEVENTMASKALL);
...
...
It first SetModEventMask to 0 (which disable all the modify notifications), and after loading, it set its value to wxSCI_MODEVENTMASKALL, this looks OK.

But I find that when the first time an OnPaint event is received, it did the following
Code
[debug]> bt 30
[debug]#0  LexAccessor::SetLevel (this=0x22ced4, line=20, level=67109888) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\lexlib\LexAccessor.h:202
[debug]#1  0x011b722a in LexerCPP::Fold(unsigned int, int, int, IDocument*)@20 (this=0x1a2e54a8, startPos=0, length=6655, initStyle=0, pAccess=0x1a30bb04) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\lexers\LexCPP.cxx:1217
[debug]#2  0x01243d40 in LexInterface::Colourise (this=0x1a2b27e8, start=0, end=6655) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\Document.cxx:65
[debug]#3  0x0124a527 in Document::EnsureStyledTo (this=0x1a30bb00, pos=6655) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\Document.cxx:1812
[debug]#4  0x01235de2 in Editor::StyleToPositionInView (this=0x1a2fbfb8, pos=6655) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\Editor.cxx:6833
[debug]#5  0x0122514d in Editor::Paint (this=0x1a2fbfb8, surfaceWindow=0x1a1979e8, rcArea=...) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\Editor.cxx:3515
[debug]#6  0x01195377 in ScintillaWX::DoPaint (this=0x1a2fbfb8, dc=0x22f1b0, rect=(0, 0) 968*215) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\ScintillaWX.cpp:924
[debug]#7  0x011901a0 in wxScintilla::OnPaint (this=0x1a196900) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\wxscintilla.cpp:5211
[debug]#8  0x04c11b0e in wxAppConsole::HandleEvent (this=0x10a24ba8, handler=0x1a196900, func=(void (wxEvtHandler::*)(wxEvtHandler * const, wxEvent &)) 0x119011e <wxScintilla::OnPaint(wxPaintEvent&)>, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\appbase.cpp:322
[debug]#9  0x04c9273d in wxEvtHandler::ProcessEventIfMatches (entry=..., handler=0x1a196900, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:1239
[debug]#10 0x04c91d53 in wxEventHashTable::HandleEvent (this=0x1518800 <cbStyledTextCtrl::sm_eventHashTable>, event=..., self=0x1a196900) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:906
[debug]#11 0x04c9293a in wxEvtHandler::ProcessEvent (this=0x1a196900, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:1301
[debug]#12 0x04cdbc20 in wxWindow::HandlePaint (this=0x1a196900) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\msw\window.cpp:4617
[debug]#13 0x04cd8830 in wxWindow::MSWWindowProc (this=0x1a196900, message=15, wParam=0, lParam=0) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\msw\window.cpp:2747
[debug]#14 0x04cd8109 in wxWndProc(HWND__*, unsigned int, unsigned int, long)@16 (hWnd=0x709c8, message=15, wParam=0, lParam=0) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\msw\window.cpp:2618
[debug]#15 0x7e418734 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll
[debug]#16 0x000709c8 in ?? ()
[debug]#17 0x0000000f in ?? ()
[debug]#18 0x00000000 in ?? ()
[debug]>>>>>>cb_gdb:
This try to set the style for each line (when SetLevel() function is called). So, for a large file which contains many lines, C::B will send many wxEVT_SCI_CHANGE events.

Do we need to allow sending all such events? I don't think so.

Hint:
I just found the Codelite's editor filter some events, see:
https://github.com/eranif/codelite/blob/master/LiteEditor/cl_editor.cpp
line 355.
Code
SetModEventMask (wxSTC_MOD_DELETETEXT | wxSTC_MOD_INSERTTEXT  | wxSTC_PERFORMED_UNDO  | wxSTC_PERFORMED_REDO | wxSTC_MOD_BEFOREDELETE | wxSTC_MOD_CHANGESTYLE);


EDIT:

Below is the backtrace of another source of events. (caused by CodeCompletion::UpdateEditorSyntax())
Code
[debug]> bt 30
[debug]#0  LexAccessor::SetLevel (this=0x22d61c, line=192, level=67175425) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\lexlib\LexAccessor.h:202
[debug]#1  0x011b722a in LexerCPP::Fold(unsigned int, int, int, IDocument*)@20 (this=0x1a2a90d8, startPos=0, length=81090, initStyle=0, pAccess=0x1a3048bc) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\lexers\LexCPP.cxx:1217
[debug]#2  0x01243d40 in LexInterface::Colourise (this=0x1a30bf48, start=0, end=81090) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\Document.cxx:65
[debug]#3  0x0124380a in ScintillaBase::WndProc (this=0x1a30a218, iMessage=4003, wParam=0, lParam=-1) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\ScintillaBase.cxx:948
[debug]#4  0x011951aa in ScintillaWX::WndProc (this=0x1a30a218, iMessage=4003, wParam=0, lParam=-1) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\ScintillaWX.cpp:898
[debug]#5  0x01184aa9 in wxScintilla::SendMsg (this=0x1a24c918, msg=4003, wp=0, lp=-1) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\wxscintilla.cpp:271
[debug]#6  0x0118df1a in wxScintilla::Colourise (this=0x1a24c918, start=0, end=-1) at F:\cb_sf_git\trunk\src\sdk\wxscintilla\src\wxscintilla.cpp:4399
[debug]#7  0x70064b20 in CodeCompletion::UpdateEditorSyntax (this=0x1245dd78, ed=0x1a24cd38) at F:\cb_sf_git\trunk\src\plugins\codecompletion\codecompletion.cpp:3320
[debug]#8  0x700658d8 in CodeCompletion::OnEditorActivatedTimer (this=0x1245dd78, event=...) at F:\cb_sf_git\trunk\src\plugins\codecompletion\codecompletion.cpp:3495
[debug]#9  0x04c11b0e in wxAppConsole::HandleEvent (this=0x10a24ba8, handler=0x1245dd78, func=(void (wxEvtHandler::*)(wxEvtHandler * const, wxEvent &)) 0x70065638 <CodeCompletion::OnEditorActivatedTimer(wxTimerEvent&)>, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\appbase.cpp:322
[debug]#10 0x04c9273d in wxEvtHandler::ProcessEventIfMatches (entry=..., handler=0x1245dd78, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:1239
[debug]#11 0x04c92d91 in wxEvtHandler::SearchDynamicEventTable (this=0x1245dd78, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:1421
[debug]#12 0x04c928f4 in wxEvtHandler::ProcessEvent (this=0x1245dd78, event=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\event.cpp:1297
[debug]#13 0x04d911e2 in wxTimerBase::Notify (this=0x1245dff8) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\common\timercmn.cpp:57
[debug]#14 0x04ccedcb in wxProcessTimer (timer=...) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\msw\timer.cpp:187
[debug]#15 0x04ccee72 in wxTimerWndProc(HWND__*, unsigned int, unsigned int, long)@16 (hWnd=0x50884, message=275, wParam=11, lParam=0) at E:\code\wx-mingw-build-481-dw2\wxWidgets-2.8.12\src\msw\timer.cpp:200
[debug]#16 0x7e418734 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll
[debug]#17 0x00050884 in ?? ()
[debug]#18 0x00000113 in ?? ()
[debug]#19 0x0000000b in ?? ()
[debug]#20 0x00000000 in ?? ()
[debug]>>>>>>cb_gdb: