Skip to content

Commit

Permalink
Fix application unresponsive when wrapping consecutive long lines, is…
Browse files Browse the repository at this point in the history
  • Loading branch information
zufuliu committed Sep 17, 2020
1 parent 6d81c09 commit d128883
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 25 deletions.
50 changes: 39 additions & 11 deletions scintilla/src/Document.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -84,33 +84,45 @@ int LexInterface::LineEndTypesSupported() const noexcept {
return 0;
}

//ActionDuration::ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept :
// duration(duration_), minDuration(minDuration_), maxDuration(maxDuration_) {
//}

void ActionDuration::AddSample(size_t numberActions, double durationOfActions) noexcept {
void ActionDuration::AddSample(Sci::Line numberActions, double durationOfActions) noexcept {
// Only adjust for multiple actions to avoid instability
if (numberActions < 8)
#if ActionDuration_MeasureTimeByBytes
if (numberActions < ActionDuration_MeasureTimeByBytes) {
return;
}
#else
if (numberActions < 8) {
return;
}
#endif

// Alpha value for exponential smoothing.
// Most recent value contributes 25% to smoothed value.
constexpr double alpha = 0.25;

#if ActionDuration_MeasureTimeByBytes
const double durationOne = (ActionDuration_MeasureTimeByBytes * durationOfActions) / numberActions;
#else
const double durationOne = durationOfActions / numberActions;
#endif
const double duration_ = alpha * durationOne + (1.0 - alpha) * duration;
//duration = std::clamp(duration_, minDuration, maxDuration);
duration = std::max(duration_, minDuration);
//printf("%s actions=%zu, one=%.9f, value=%.9f, [%.9f, %f, %f]\n", __func__,
// numberActions, durationOne, duration_, duration, minDuration, maxDuration);
//printf("%s actions=%.9f / %zd, one=%.9f, value=%.9f, [%.9f, %f, %f]\n", __func__,
// durationOfActions, numberActions, durationOne, duration_, duration, minDuration, maxDuration);
}

double ActionDuration::Duration() const noexcept {
return duration;
}

Sci::Line ActionDuration::LinesInAllowedTime(double secondsAllowed) const noexcept {
return std::clamp<Sci::Line>(static_cast<Sci::Line>(secondsAllowed / duration), 8, 0x10000);
Sci::Line ActionDuration::ActionsInAllowedTime(double secondsAllowed) const noexcept {
const Sci::Line actions = std::clamp<Sci::Line>(static_cast<Sci::Line>(secondsAllowed / duration), 8, 0x10000);
#if ActionDuration_MeasureTimeByBytes
return actions * ActionDuration_MeasureTimeByBytes;
#else
return actions;
#endif
}

Document::Document(int options) :
Expand Down Expand Up @@ -490,6 +502,17 @@ Sci::Line Document::LineFromPositionIndex(Sci::Position pos, int lineCharacterIn
return cb.LineFromPositionIndex(pos, lineCharacterIndex);
}

#if ActionDuration_MeasureTimeByBytes
Sci::Line Document::LineFromPositionAfter(Sci::Line line, Sci::Position length) const noexcept {
const Sci::Position pos = LineStart(line) + length;
if (pos >= Length()) {
return LinesTotal();
}
const Sci::Line lineLast = SciLineFromPosition(pos);
return lineLast + (!!(line == lineLast));
}
#endif

int SCI_METHOD Document::SetLevel(Sci_Position line, int level) {
const int prev = Levels()->SetLevel(line, level, LinesTotal());
if (prev != level) {
Expand Down Expand Up @@ -2246,7 +2269,12 @@ void Document::StyleToAdjustingLineDuration(Sci::Position pos) {
ElapsedPeriod epStyling;
EnsureStyledTo(pos);
const Sci::Line lineLast = SciLineFromPosition(GetEndStyled());
durationStyleOneLine.AddSample(lineLast - lineFirst, epStyling.Duration());
#if ActionDuration_MeasureTimeByBytes
const Sci::Line actions = LineStart(lineLast) - LineStart(lineFirst);
#else
const Sci::Line actions = lineLast - lineFirst;
#endif
durationStyleOneLine.AddSample(actions, epStyling.Duration());
}

void Document::LexerChanged() {
Expand Down
12 changes: 9 additions & 3 deletions scintilla/src/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,18 @@ struct RegexError : public std::runtime_error {
* experience.
*/

//#define ActionDuration_MeasureTimeByBytes 0 // measure time by line
#define ActionDuration_MeasureTimeByBytes 1024
#define ActionDuration_InitializedMaxBytes (1024*1024)

class ActionDuration {
double duration = 1e-5;
static constexpr double minDuration = 1e-6;
static constexpr double maxDuration = 1e-4;
public:
//ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept;
void AddSample(size_t numberActions, double durationOfActions) noexcept;
void AddSample(Sci::Line numberActions, double durationOfActions) noexcept;
double Duration() const noexcept;
Sci::Line LinesInAllowedTime(double secondsAllowed) const noexcept;
Sci::Line ActionsInAllowedTime(double secondsAllowed) const noexcept;
};

/**
Expand Down Expand Up @@ -472,6 +475,9 @@ class Document : PerLine, public IDocument, public ILoader {
Sci::Position VCHomePosition(Sci::Position position) const noexcept;
Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept;
Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept;
#if ActionDuration_MeasureTimeByBytes
Sci::Line LineFromPositionAfter(Sci::Line line, Sci::Position length) const noexcept;
#endif

int SCI_METHOD SetLevel(Sci_Position line, int level) override;
int SCI_METHOD GetLevel(Sci_Position line) const noexcept override;
Expand Down
38 changes: 27 additions & 11 deletions scintilla/src/Editor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,6 @@ bool Editor::WrapLines(WrapScope ws) {
wrapOccurred = true;
}
wrapPending.Reset();

} else if (wrapPending.NeedsWrap()) {
wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal());
if (!SetIdle(true)) {
Expand All @@ -1540,7 +1539,13 @@ bool Editor::WrapLines(WrapScope ws) {
// as taking only one display line.
lineToWrapEnd = lineDocTop;
Sci::Line lines = LinesOnScreen() + 1;
while ((lineToWrapEnd < pcs->LinesInDoc()) && (lines > 0)) {
#if ActionDuration_MeasureTimeByBytes
const Sci::Line lineLast = pdoc->LineFromPositionAfter(lineToWrap, ActionDuration_InitializedMaxBytes);
const Sci::Line maxLine = std::min(lineLast, pcs->LinesInDoc());
#else
const Sci::Line maxLine = pcs->LinesInDoc();
#endif
while ((lineToWrapEnd < maxLine) && (lines > 0)) {
if (pcs->GetVisible(lineToWrapEnd))
lines--;
lineToWrapEnd++;
Expand All @@ -1553,8 +1558,12 @@ bool Editor::WrapLines(WrapScope ws) {
} else if (ws == WrapScope::wsIdle) {
// Try to keep time taken by wrapping reasonable so interaction remains smooth.
constexpr double secondsAllowed = 0.01;
const Sci::Line linesInAllowedTime = durationWrapOneLine.LinesInAllowedTime(secondsAllowed);
lineToWrapEnd = lineToWrap + linesInAllowedTime;
const Sci::Line actions = durationWrapOneLine.ActionsInAllowedTime(secondsAllowed);
#if ActionDuration_MeasureTimeByBytes
lineToWrapEnd = pdoc->LineFromPositionAfter(lineToWrap, actions);
#else
lineToWrapEnd = lineToWrap + actions;
#endif
}
const Sci::Line lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal());
lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap);
Expand All @@ -1572,8 +1581,11 @@ bool Editor::WrapLines(WrapScope ws) {
AutoSurface surface(this);
if (surface) {
//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);

const Sci::Line linesBeingWrapped = lineToWrapEnd - lineToWrap;
#if ActionDuration_MeasureTimeByBytes
const Sci::Line actions = pdoc->LineStart(lineToWrapEnd) - pdoc->LineStart(lineToWrap);
#else
const Sci::Line actions = lineToWrapEnd - lineToWrap;
#endif
ElapsedPeriod epWrapping;
while (lineToWrap < lineToWrapEnd) {
if (WrapOneLine(surface, lineToWrap)) {
Expand All @@ -1582,7 +1594,7 @@ bool Editor::WrapLines(WrapScope ws) {
wrapPending.Wrapped(lineToWrap);
lineToWrap++;
}
durationWrapOneLine.AddSample(linesBeingWrapped, epWrapping.Duration());
durationWrapOneLine.AddSample(actions, epWrapping.Duration());

goodTopLine = pcs->DisplayFromDoc(lineDocTop) + std::min(
subLineTop, static_cast<Sci::Line>(pcs->GetHeight(lineDocTop) - 1));
Expand Down Expand Up @@ -5114,11 +5126,15 @@ Sci::Position Editor::PositionAfterMaxStyling(Sci::Position posMax, bool scrolli
// Try to keep time taken by styling reasonable so interaction remains smooth.
// When scrolling, allow less time to ensure responsive
const double secondsAllowed = scrolling ? 0.005 : 0.02;
const Sci::Line linesToStyle = pdoc->durationStyleOneLine.LinesInAllowedTime(secondsAllowed);
Sci::Line lineStart = pdoc->SciLineFromPosition(pdoc->GetEndStyled());
const Sci::Line actions = pdoc->durationStyleOneLine.ActionsInAllowedTime(secondsAllowed);
#if ActionDuration_MeasureTimeByBytes
lineStart = pdoc->LineFromPositionAfter(lineStart, actions);
#else
lineStart += actions;
#endif

const Sci::Line stylingMaxLine = std::min(
pdoc->SciLineFromPosition(pdoc->GetEndStyled()) + linesToStyle,
pdoc->LinesTotal());
const Sci::Line stylingMaxLine = std::min(lineStart, pdoc->LinesTotal());
return std::min(pdoc->LineStart(stylingMaxLine), posMax);
}

Expand Down

0 comments on commit d128883

Please sign in to comment.