Author Topic: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages  (Read 15737 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« 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.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #1 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... :-)
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #2 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. :(
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #3 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).
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #4 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.

« Last Edit: July 19, 2013, 04:13:29 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #5 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. :)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #6 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?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #7 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.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5905
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Flood of wxEVT_SCI_MODIFIED and wxEVT_SCI_CHANGE messages
« Reply #8 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:


« Last Edit: June 08, 2014, 04:16:10 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.