mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-25 21:35:33 +00:00
Implement adaptive ETA calculation based on observed segment durations
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
This commit is contained in:
co-authored by
ashaduri
parent
2ef695f8fb
commit
1c99ff8350
@@ -44,3 +44,4 @@ Thumbs.db
|
||||
/po/gsmartcontrol.pot
|
||||
/po/*.gmo
|
||||
|
||||
build/
|
||||
|
||||
+30
-1
@@ -93,7 +93,30 @@ std::chrono::seconds SelfTest::get_remaining_seconds() const
|
||||
if (total <= 0s)
|
||||
return -1s; // unknown
|
||||
|
||||
const double gran = (double(total.count()) / 9.); // seconds per 10%
|
||||
const double gran = (double(total.count()) / 9.); // seconds per 10% (drive estimate)
|
||||
|
||||
// Use adaptive estimation if we have observed at least one completed segment
|
||||
if (!segment_durations_.empty()) {
|
||||
// Calculate average duration of observed segments
|
||||
double sum = 0.0;
|
||||
for (const auto& duration : segment_durations_) {
|
||||
sum += duration;
|
||||
}
|
||||
const double avg_segment_duration = sum / segment_durations_.size();
|
||||
|
||||
// Estimate remaining time based on observed average and remaining segments
|
||||
// remaining_percent_ goes from 100 (start) to 0 (end), in 10% decrements
|
||||
const int8_t remaining_segments = (remaining_percent_ + 9) / 10; // round up
|
||||
const double estimated_remaining = avg_segment_duration * remaining_segments - timer_.elapsed();
|
||||
|
||||
const auto rem_rounded = static_cast<int64_t>(std::round(estimated_remaining));
|
||||
if (rem_rounded < 0) {
|
||||
return -1s; // estimate exhausted; return unknown
|
||||
}
|
||||
return std::chrono::seconds(rem_rounded);
|
||||
}
|
||||
|
||||
// Fall back to drive's initial estimate when we don't have observed data yet
|
||||
// since remaining_percent_ may be manually set to 100, we limit from the above.
|
||||
const double rem_seconds_at_last_change = std::min(double(total.count()), gran * remaining_percent_ / 10.);
|
||||
const double rem = rem_seconds_at_last_change - timer_.elapsed();
|
||||
@@ -499,6 +522,12 @@ hz::ExpectedVoid<SelfTestExecutionError> SelfTest::update(const std::shared_ptr<
|
||||
// and reaches 00% on completion. That's 9 pieces.
|
||||
if (status_ == SelfTestStatus::InProgress) {
|
||||
if (remaining_percent_ != last_seen_percent_) {
|
||||
// Record the duration of the completed segment for adaptive ETA calculation
|
||||
if (last_seen_percent_ != -1 && last_seen_percent_ != 90) {
|
||||
// Don't record the initial 100->90 transition (no real work done yet)
|
||||
const double elapsed = timer_.elapsed();
|
||||
segment_durations_.push_back(elapsed);
|
||||
}
|
||||
last_seen_percent_ = remaining_percent_;
|
||||
timer_.start(); // restart the timer
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ Copyright:
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "storage_device.h"
|
||||
#include "command_executor.h"
|
||||
@@ -126,6 +127,12 @@ class SelfTest {
|
||||
|
||||
|
||||
/// Get estimated time of completion for the test.
|
||||
/// The estimation uses an adaptive algorithm:
|
||||
/// - Initially uses the drive's reported test duration estimate
|
||||
/// - After completing one or more 10% segments, switches to using the observed
|
||||
/// average segment duration to predict remaining time
|
||||
/// - This provides more accurate ETAs when the drive's estimate is inaccurate
|
||||
/// (e.g., under load or with drives that consistently under/overestimate)
|
||||
/// \return -1 if N/A or unknown (including when the drive's estimated duration has been
|
||||
/// exceeded without a percentage change, which means the estimate was inaccurate).
|
||||
/// Note that 0 is a valid value meaning the test is finishing right now.
|
||||
@@ -182,6 +189,7 @@ class SelfTest {
|
||||
std::chrono::seconds poll_in_seconds_ = std::chrono::seconds(-1); ///< The user is asked to poll after this much seconds have passed.
|
||||
|
||||
Glib::Timer timer_; ///< Counts time since the last percent change
|
||||
std::vector<double> segment_durations_; ///< Actual durations of completed 10% segments (in seconds), for adaptive ETA calculation
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user