core/renderjournal: improve render time heuristics

Instead of giving the rolling average for render times a special case for
when render time suddenly increases, detect how stable render times are.
If they're volatile and increase a lot, increase the predicated render time
beyond the spike, as more render time spikes are likely to follow.

CCBUG: 477959
This commit is contained in:
Xaver Hugl 2024-01-18 16:53:11 +01:00
parent 7ba7ddfee8
commit 9822e75fbf
3 changed files with 24 additions and 14 deletions

View file

@ -6,6 +6,8 @@
#include "renderjournal.h"
using namespace std::chrono_literals;
namespace KWin
{
@ -13,22 +15,29 @@ RenderJournal::RenderJournal()
{
}
void RenderJournal::add(std::chrono::nanoseconds renderTime)
static std::chrono::nanoseconds mix(std::chrono::nanoseconds duration1, std::chrono::nanoseconds duration2, double ratio)
{
if (renderTime > m_result || !m_lastAdd) {
m_result = renderTime;
} else {
static constexpr std::chrono::nanoseconds timeConstant = std::chrono::milliseconds(500);
const auto timeDifference = std::chrono::steady_clock::now() - *m_lastAdd;
const double ratio = std::min(0.1, double(timeDifference.count()) / double(timeConstant.count()));
m_result = std::chrono::nanoseconds(int64_t(renderTime.count() * ratio + m_result.count() * (1 - ratio)));
}
m_lastAdd = std::chrono::steady_clock::now();
return std::chrono::nanoseconds(int64_t(std::round(duration1.count() * ratio + duration2.count() * (1 - ratio))));
}
void RenderJournal::add(std::chrono::nanoseconds renderTime, std::chrono::nanoseconds presentationTimestamp)
{
const auto timeDifference = m_lastAdd ? presentationTimestamp - *m_lastAdd : 10s;
m_lastAdd = presentationTimestamp;
static constexpr std::chrono::nanoseconds varianceTimeConstant = 3s;
const double varianceRatio = std::clamp(timeDifference.count() / double(varianceTimeConstant.count()), 0.1, 1.0);
const auto renderTimeDiff = std::max(renderTime - m_result, 0ns);
m_variance = std::max(mix(renderTimeDiff, m_variance, varianceRatio), renderTimeDiff);
static constexpr std::chrono::nanoseconds timeConstant = 500ms;
const double ratio = std::clamp(timeDifference.count() / double(timeConstant.count()), 0.1, 1.0);
m_result = mix(renderTime, m_result, ratio);
}
std::chrono::nanoseconds RenderJournal::result() const
{
return m_result;
return m_result + m_variance * 2;
}
} // namespace KWin

View file

@ -23,13 +23,14 @@ class KWIN_EXPORT RenderJournal
public:
RenderJournal();
void add(std::chrono::nanoseconds renderTime);
void add(std::chrono::nanoseconds renderTime, std::chrono::nanoseconds presentationTimestamp);
std::chrono::nanoseconds result() const;
private:
std::chrono::nanoseconds m_result{0};
std::optional<std::chrono::steady_clock::time_point> m_lastAdd;
std::chrono::nanoseconds m_variance{0};
std::optional<std::chrono::nanoseconds> m_lastAdd;
};
} // namespace KWin

View file

@ -97,7 +97,7 @@ void RenderLoopPrivate::notifyFrameCompleted(std::chrono::nanoseconds timestamp,
notifyVblank(timestamp);
renderJournal.add(renderTime);
renderJournal.add(renderTime, timestamp);
if (!inhibitCount) {
maybeScheduleRepaint();
}