Menu

#851 Show length of selected text

Undefined
open
None
Feature_Request
2019-09-27
2019-07-16
Zdena K
No

Hello,
please add an indicator of selected text length to the status bar.
Solution exists:
http://forums.codeblocks.org/index.php/topic,23273.msg158503.html#msg158503

1 Attachments

Discussion

  • Zdena K

    Zdena K - 2019-08-25

    Hello, I tried to create a patch for it (this is BlueHazzard's patch in reality). It's my first patch post (and I never worked with svn and so on) so please be tolerant if I did it wrong way.

    Edit: Corrected one error in the patch.

     

    Last edit: Zdena K 2019-08-25
  • Teodor Petrov

    Teodor Petrov - 2019-08-28

    As stated in the topic this patch is not acceptable. If we're going to add something here we should make this configurable (with formatting like strings)!

     
  • bluehazzard

    bluehazzard - 2019-08-29
    • assigned_to: bluehazzard
     
  • bluehazzard

    bluehazzard - 2019-08-29

    Here is a patch with dynamic formatting and nice tags

     
  • Teodor Petrov

    Teodor Petrov - 2019-08-30

    Can you measure the performance impact of this change? This happens very often and shouldn't add delays to the editor!

     
  • bluehazzard

    bluehazzard - 2019-08-30

    Ok, some performance on my pc: All numbers are returned from QueryPerformanceCounter https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter

    This is a raw implementation in a new program:

    Old implementation (without selection display)
    Duration: 41.6641 , min: 35, max: 386, count: 10000
    Duration: 43.0685 , min: 34, max: 478, count: 10000
    Duration: 41.5154 , min: 35, max: 468, count: 10000
    Duration: 40.7124 , min: 35, max: 359, count: 10000
    Duration: 42.0436 , min: 35, max: 294, count: 10000
    Duration: 40.2498 , min: 34, max: 465, count: 10000
    Duration: 42.2045 , min: 35, max: 3513, count: 10000
    Duration: 43.1462 , min: 35, max: 520, count: 10000
    Duration: 39.3445 , min: 34, max: 261, count: 10000
    Duration: 40.3568 , min: 34, max: 313, count: 10000
    Duration: 42.0852 , min: 35, max: 418, count: 10000
    Duration: 41.8663 , min: 35, max: 454, count: 10000
    Duration: 41.0343 , min: 35, max: 458, count: 10000
    Duration: 40.3655 , min: 35, max: 340, count: 10000
    Duration: 41.511 , min: 35, max: 342, count: 10000
    Duration: 42.37 , min: 35, max: 341, count: 10000
    Duration: 40.8679 , min: 35, max: 444, count: 10000
    Duration: 41.9529 , min: 34, max: 523, count: 10000
    Duration: 40.8303 , min: 34, max: 364, count: 10000
    
    New Implementation (with selection display)
    Duration: 80.4447 , min: 66, max: 766, count: 10000
    Duration: 81.6317 , min: 66, max: 638, count: 10000
    Duration: 79.4575 , min: 67, max: 1109, count: 10000
    Duration: 77.9361 , min: 67, max: 383, count: 10000
    Duration: 81.8575 , min: 67, max: 612, count: 10000
    Duration: 97.8307 , min: 67, max: 3672, count: 10000
    Duration: 97.6453 , min: 67, max: 598, count: 10000
    Duration: 97.7329 , min: 70, max: 539, count: 10000
    Duration: 92.5459 , min: 72, max: 357, count: 10000
    Duration: 77.3541 , min: 67, max: 745, count: 10000
    Duration: 79.6439 , min: 66, max: 674, count: 10000
    Duration: 79.6707 , min: 66, max: 518, count: 10000
    Duration: 84.6628 , min: 66, max: 643, count: 10000
    Duration: 77.4203 , min: 66, max: 987, count: 10000
    Duration: 79.6052 , min: 66, max: 594, count: 10000
    Duration: 83.6269 , min: 69, max: 3713, count: 10000
    Duration: 80.4709 , min: 66, max: 503, count: 10000
    Duration: 80.1143 , min: 66, max: 471, count: 10000
    Duration: 76.4735 , min: 66, max: 791, count: 10000
    Duration: 80.4669 , min: 67, max: 5612, count: 10000
    

    So in the test setup the new implementation is half as fast...

    This implementation is in codeblocks under the real code:

    Old implementation
    Duration: 239.804 , min: 174, max: 486, count: 51
    Duration: 232.471 , min: 170, max: 628, count: 51
    Duration: 219.647 , min: 115, max: 389, count: 51
    Duration: 301.98 , min: 143, max: 1737, count: 51
    Duration: 230.392 , min: 137, max: 548, count: 51
    Duration: 227.706 , min: 171, max: 555, count: 51
    Duration: 221.314 , min: 153, max: 376, count: 51
    Duration: 235.039 , min: 173, max: 776, count: 51
    Duration: 216.235 , min: 145, max: 368, count: 51
    
    new implementation
    Duration: 227.843 , min: 158, max: 425, count: 51
    Duration: 230.431 , min: 169, max: 1096, count: 51
    Duration: 270.373 , min: 170, max: 1740, count: 51
    Duration: 250.902 , min: 144, max: 1320, count: 51
    Duration: 253.765 , min: 144, max: 1891, count: 51
    Duration: 251.765 , min: 145, max: 1650, count: 51
    Duration: 263.922 , min: 165, max: 1140, count: 51
    Duration: 327.824 , min: 158, max: 1962, count: 51
    Duration: 249.706 , min: 174, max: 1057, count: 51
    Duration: 261.392 , min: 172, max: 1575, count: 51
    

    so the real impact is low... Good measurement is hard, because my pc is not on idle...
    i am not sure why though

     
  • Teodor Petrov

    Teodor Petrov - 2019-08-31

    What are the units of time? Seconds, miliseconds, microseconds?
    And how do you measure inside codeblocks? Why do you have count=51?

    If I'm you I'd measure the impact on the whole statusbar handling. If it is not visibly slower I'll be fine. Also make sure you test with all fields added. :) The whole status bar handling must not be above 1ms or ideally not above 0.1ms.

    p.s. If you want to do microbenchmarks, just use a benchmark library like google benchmark.
    p.p.s. What is your cpu, just for reference?

     

    Last edit: Teodor Petrov 2019-08-31
  • bluehazzard

    bluehazzard - 2019-09-01

    So new benchmark:
    Setup:
    I use the same timer function as above from windows, Windows 7 wx302, AMD Phenon X2
    I measure the time needed to create the status bar in codeblocks. For this i have to move the mouse cursor and select text. I sample 100 times and print statistical data from them:

    Old printf
    mean: 3.988ms | min: 2.855ms | max:  8.160ms | var: 0.818ms | count: 100
    mean: 3.890ms | min: 2.792ms | max:  7.666ms | var: 0.715ms | count: 100
    mean: 4.018ms | min: 2.845ms | max: 16.652ms | var: 1.521ms | count: 100
    mean: 3.885ms | min: 2.860ms | max:  6.170ms | var: 0.713ms | count: 100
    mean: 3.761ms | min: 2.972ms | max:  6.463ms | var: 0.510ms | count: 100
    mean: 3.999ms | min: 2.933ms | max:  8.477ms | var: 0.922ms | count: 100
    mean: 3.639ms | min: 2.801ms | max:  4.864ms | var: 0.448ms | count: 100
    mean: 3.959ms | min: 0.523ms | max:  8.609ms | var: 0.966ms | count: 100
    mean: 3.827ms | min: 2.899ms | max:  6.238ms | var: 0.558ms | count: 100
    mean: 3.769ms | min: 2.904ms | max:  7.201ms | var: 0.666ms | count: 100
    mean: 3.736ms | min: 0.611ms | max:  6.263ms | var: 0.713ms | count: 100
    mean: 3.822ms | min: 2.840ms | max:  6.199ms | var: 0.655ms | count: 100
    mean: 3.668ms | min: 2.870ms | max:  6.688ms | var: 0.587ms | count: 100
    mean: 3.683ms | min: 2.865ms | max:  5.749ms | var: 0.510ms | count: 100
    
    New implementation: print string: Line [line], Col [col], Pos [pos]
    mean: 4.036ms | min: 0.601ms | max: 19.521ms | var: 1.913ms | count: 100
    mean: 4.393ms | min: 3.207ms | max: 15.268ms | var: 1.289ms | count: 100
    mean: 4.381ms | min: 3.012ms | max:  8.194ms | var: 0.904ms | count: 100
    mean: 4.242ms | min: 3.139ms | max:  6.717ms | var: 0.715ms | count: 100
    mean: 4.253ms | min: 3.144ms | max:  9.284ms | var: 0.987ms | count: 100
    mean: 4.116ms | min: 3.021ms | max:  9.079ms | var: 0.875ms | count: 100
    mean: 4.423ms | min: 2.870ms | max:  9.264ms | var: 1.019ms | count: 100
    mean: 4.441ms | min: 2.958ms | max:  9.939ms | var: 1.236ms | count: 100
    mean: 4.279ms | min: 2.889ms | max: 11.684ms | var: 1.180ms | count: 100
    mean: 4.352ms | min: 2.919ms | max: 12.398ms | var: 1.183ms | count: 100
    mean: 4.167ms | min: 2.919ms | max:  9.758ms | var: 0.882ms | count: 100
    mean: 4.469ms | min: 3.036ms | max: 10.902ms | var: 0.967ms | count: 100
    mean: 4.226ms | min: 2.958ms | max:  7.548ms | var: 0.749ms | count: 100
    mean: 4.267ms | min: 3.276ms | max: 12.237ms | var: 0.981ms | count: 100
    
    New implementation: print string Line [line], Col [col], Pos [pos], Sel[sel] (aka this patch)
    mean: 3.778ms | min: 0.670ms | max:  9.167ms | var: 1.097ms | count: 100        
    mean: 3.827ms | min: 2.889ms | max: 10.516ms | var: 0.876ms | count: 100        
    mean: 3.711ms | min: 2.767ms | max:  5.348ms | var: 0.526ms | count: 100        
    mean: 3.863ms | min: 2.806ms | max:  9.680ms | var: 0.884ms | count: 100        
    mean: 3.909ms | min: 2.699ms | max:  7.226ms | var: 0.822ms | count: 100        
    mean: 3.889ms | min: 2.752ms | max:  6.835ms | var: 0.808ms | count: 100        
    mean: 3.750ms | min: 2.767ms | max:  5.759ms | var: 0.499ms | count: 100        
    mean: 3.806ms | min: 2.845ms | max:  8.428ms | var: 0.868ms | count: 100        
    mean: 3.899ms | min: 2.660ms | max: 12.667ms | var: 1.096ms | count: 100        
    mean: 3.897ms | min: 2.660ms | max: 10.624ms | var: 1.011ms | count: 100        
    mean: 4.034ms | min: 2.645ms | max:  7.993ms | var: 0.825ms | count: 100        
    mean: 3.693ms | min: 2.772ms | max:  7.128ms | var: 0.737ms | count: 100        
    mean: 3.596ms | min: 2.723ms | max:  5.500ms | var: 0.457ms | count: 100        
    mean: 3.693ms | min: 2.855ms | max:  6.805ms | var: 0.577ms | count: 100        
    
    Old printf with position arguments without selection (use "Line %1$d, Col %2$d, Pos %3$d"
    mean: 3.968ms | min: 0.396ms | max: 16.089ms | var: 1.440ms | count: 100
    mean: 3.922ms | min: 2.899ms | max:  8.663ms | var: 0.776ms | count: 100
    mean: 3.771ms | min: 2.938ms | max:  6.395ms | var: 0.505ms | count: 100
    mean: 3.810ms | min: 2.992ms | max:  8.653ms | var: 0.670ms | count: 100
    mean: 3.890ms | min: 0.660ms | max:  9.245ms | var: 0.878ms | count: 100
    mean: 3.813ms | min: 2.914ms | max:  6.517ms | var: 0.571ms | count: 100
    mean: 3.867ms | min: 2.889ms | max:  5.769ms | var: 0.572ms | count: 100
    mean: 4.039ms | min: 2.870ms | max:  8.311ms | var: 0.986ms | count: 100
    mean: 4.094ms | min: 2.928ms | max:  7.460ms | var: 0.828ms | count: 100
    mean: 3.787ms | min: 2.796ms | max:  6.409ms | var: 0.610ms | count: 100
    mean: 3.940ms | min: 2.919ms | max:  6.605ms | var: 0.723ms | count: 100
    mean: 4.036ms | min: 2.948ms | max:  6.605ms | var: 0.677ms | count: 100
    mean: 4.002ms | min: 2.933ms | max:  9.832ms | var: 0.976ms | count: 100
    mean: 4.189ms | min: 2.924ms | max: 10.027ms | var: 1.141ms | count: 100
    
    Old printf with position arguments without selection
    mean: 4.735ms | min: 0.631ms | max: 16.089ms | var: 1.738ms | count: 100
    mean: 4.949ms | min: 3.852ms | max:  9.255ms | var: 0.868ms | count: 100
    mean: 5.291ms | min: 2.924ms | max: 23.129ms | var: 2.254ms | count: 100
    mean: 5.321ms | min: 3.261ms | max: 18.167ms | var: 1.854ms | count: 100
    mean: 5.168ms | min: 3.623ms | max: 22.269ms | var: 2.023ms | count: 100
    mean: 4.740ms | min: 3.711ms | max:  7.402ms | var: 0.766ms | count: 100
    mean: 4.884ms | min: 3.046ms | max: 14.549ms | var: 1.441ms | count: 100
    mean: 4.657ms | min: 0.733ms | max:  8.448ms | var: 1.066ms | count: 100
    mean: 5.092ms | min: 3.755ms | max: 14.334ms | var: 1.672ms | count: 100
    mean: 4.968ms | min: 3.735ms | max: 11.719ms | var: 1.255ms | count: 100
    mean: 5.005ms | min: 3.725ms | max: 15.136ms | var: 1.436ms | count: 100
    mean: 4.829ms | min: 3.750ms | max: 29.099ms | var: 2.565ms | count: 100
    mean: 4.915ms | min: 3.662ms | max: 15.121ms | var: 1.447ms | count: 100
    mean: 5.129ms | min: 3.354ms | max: 10.653ms | var: 1.236ms | count: 100
    

    And because this is not nice to see i made a plot and attached it

     
  • bluehazzard

    bluehazzard - 2019-09-01

    Conclusion, this patch does not make things slower in avarage. The build time is ca 4ms of the whole status bar

     
  • Teodor Petrov

    Teodor Petrov - 2019-09-02

    Can I see your measuring code? 4ms for statusbar refresh is massive amount of time. :(

     
  • bluehazzard

    bluehazzard - 2019-09-03

    calculation of values is not optimized, because it is outside of the time measurement

    static std::vector<int64_t> summ;
    
    void MainFrame::DoUpdateStatusBar()
    {
        if (!GetStatusBar())
            return;
        if (Manager::IsAppShuttingDown())
            return;
    
        LARGE_INTEGER freq, time_begin, time_end;
    
        cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
        wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
        if (ed)
        {
            QueryPerformanceCounter(&time_begin);
            cbStyledTextCtrl * const control = ed->GetControl();
    
            int panel = 0;
            int pos = control->GetCurrentPos();
            wxString msg;
            SetStatusText(ed->GetFilename(), panel++);
    
            // Highlightbutton
            if (m_pHighlightButton)
            {
                EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
                if (colour_set)
                    changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(ed->GetLanguage()));
                else
                    changeButtonLabel(*m_pHighlightButton, wxEmptyString);
            }
            // EOL mode
            panel++;
            switch (control->GetEOLMode())
            {
                case wxSCI_EOL_CRLF: msg = _T("Windows (CR+LF)"); break;
                case wxSCI_EOL_CR:   msg = _T("Mac (CR)");        break;
                case wxSCI_EOL_LF:   msg = _T("Unix (LF)");       break;
                default:                                          break;
            }
            SetStatusText(msg, panel++);
            SetStatusText(ed->GetEncodingName(), panel++);
    
            wxString statusFormat(m_StatusBarFormatString);
            statusFormat.Replace(_T("[line]"), wxString::Format(_T("%d"), control->GetCurrentLine() + 1));
            statusFormat.Replace(_T("[col]"), wxString::Format(_T("%d"), control->GetColumn(pos) + 1));
            statusFormat.Replace(_T("[pos]"), wxString::Format(_T("%d"), pos));
            statusFormat.Replace(_T("[sel]"), wxString::Format(_T("%d"), control->GetSelectionEnd() - control->GetSelectionStart()));
            SetStatusText(statusFormat, panel++);
            //msg.Printf(_("Line %3$d, Col %2$d, Pos %1$d, Sel %4$d"),pos, control->GetCurrentLine() + 1, control->GetColumn(pos) + 1, control->GetSelectionEnd() - control->GetSelectionStart());
            //SetStatusText(msg, panel++);
    
            SetStatusText(control->GetOvertype() ? _("Overwrite") : _("Insert"), panel++);
    #if wxCHECK_VERSION(3, 0, 0)
            SetStatusText(ed->GetModified() ? _("Modified") : _T(""), panel++);
    #else
            SetStatusText(ed->GetModified() ? _("Modified") : wxEmptyString, panel++);
    #endif
            SetStatusText(control->GetReadOnly() ? _("Read only") : _("Read/Write"), panel++);
            SetStatusText(personality, panel++);
    
            QueryPerformanceCounter(&time_end);
    
            int64_t su = time_end.QuadPart - time_begin.QuadPart;
    
            summ.push_back(su);
    
            if(summ.size() == 100)
            {
                QueryPerformanceFrequency(&freq);
    
                int64_t summe = 0;
                int64_t smax = std::numeric_limits<int64_t>::min();
                int64_t smin = std::numeric_limits<int64_t>::max();
                for(auto item : summ)
                {
                    smax = std::max(item, smax);
                    smin = std::min(item, smin);
                    summe += item;
                }
    
                const double mean = (double) summe / summ.size();
    
                double deviation = 0.0;
    
                for(auto item : summ)
                    deviation += (item - mean) * (item - mean);
    
                deviation = deviation / summ.size();
    
                deviation = (sqrt(deviation) * 10E3) / (double) freq.QuadPart;
                const double tmax = (double) smax * 10E3 / (double) freq.QuadPart;
                const double tmin = (double) smin * 10E3 / (double) freq.QuadPart;
                const double tmean = (double) mean * 10E3 / (double) freq.QuadPart;
    
                wxString out = wxString::Format("mean: %3.3lfms | min: %03.3lfms | max: %03.3lfms | var: %03.3lfms | count: %d", tmean, tmin, tmax, deviation, (int) summ.size());
                Manager::Get()->GetLogManager()->Log(out);
                summ.clear();
            }
        }
        else
        {
            int panel = 0;
            EditorBase *eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
            if ( eb )
                SetStatusText(eb->GetFilename(), panel++);
            else
                SetStatusText(_("Welcome to ") + appglobals::AppName + _T("!"), panel++);
    
            // Highlightbutton
            if (m_pHighlightButton)
                changeButtonLabel(*m_pHighlightButton, wxEmptyString);
            panel++;
    
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(wxEmptyString, panel++);
            SetStatusText(personality, panel++);
        }
    }
    

    [edit:] fixed code... had some errors in it

     

    Last edit: bluehazzard 2019-09-03
  • bluehazzard

    bluehazzard - 2019-09-03

    i forgot to mention: i do compile with -g and no optimization...
    [Edit:] With optimization 03 it is not better... avg 3.6ms with patch from top

     

    Last edit: bluehazzard 2019-09-03
  • Teodor Petrov

    Teodor Petrov - 2019-09-03
    1. Why don't you measure the whole function?
    2. Why do you do batches of 100, just calc the stats on the whole sample set.
    3. Are you sure there is no frequency scaling?
    4. Is everything else stopped (browser, chat, something else)?
    5. Still 3.6ms is pretty expensive for this function. What is the file you're editing.
    6. I guess you can push this change and we could optimize it later.
     
  • bluehazzard

    bluehazzard - 2019-09-03

    Why don't you measure the whole function?
    Does it really make a difference? The workload that needs the time (and we want to optimize) is in the time measurement part

    Why do you do batches of 100, just calc the stats on the whole sample set.
    I do want to mitigate CPU spikes by using batches of the avarage and find and ignore lokal maxima. Also i want to move the mouse only a few times until i see a result...

    Are you sure there is no frequency scaling?
    Of what? CPU? Can be...

    Is everything else stopped (browser, chat, something else)?
    No my normal programs are open (Browser, that even takes some CPU in the 5% (thank you fu java script and bloated webpages))

    Still 3.6ms is pretty expensive for this function. What is the file you're editing.
    Some normal 300 line code... I too think 3.6ms is too much, but i do not notice any slowdown, flashing or other fuzzyness. And my working PC is 10 Years old...

    I guess you can push this change and we could optimize it later.
    I will experiment a bit and if i do not find any speedup i will push it...

     
  • Zdena K

    Zdena K - 2019-09-06

    If I can say anything to it, it works for me. And I don't see any influence on performance. No measurements, only feeling. Well done, bluehazzard.

     
  • bluehazzard

    bluehazzard - 2019-09-18

    Here is a other idea... No cleanup, and there is still a bug when you change the status bar setting, i just wanted to know if this idea pleases more.

    (sadly c++ still does not have fast, typesafe flags...)

    Clean up formatting is needed, also probably more encapsulation, but it is to late for this now.... But this concept would add nearly no overhead over the old system...

     

    Last edit: bluehazzard 2019-09-18
  • Teodor Petrov

    Teodor Petrov - 2019-09-20

    Does it imporve performance? If it doesn't there is no need for such additional complexity.

     
  • bluehazzard

    bluehazzard - 2019-09-25

    Ok this is my final proposal.
    The performance impact for the default string replacing is minimal. Adding the selection part does slow down a bit, but there is scintilla the slow part. With the implemented flags this does not occure if the selection is not put in the status bar.

    i choosed the struct way over the previous type safe flag way for readability... I checked the performace of assambler code and it si as good as it can get when -O3 is enabled...

     
  • Teodor Petrov

    Teodor Petrov - 2019-09-27

    What are the numbers?

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.