ProgressInfo::Estimates ProgressInfo::totalProgress() const { Estimates file = _fileProgress.estimates(); if (_sizeProgress._total == 0) { return file; } Estimates size = _sizeProgress.estimates(); // Ideally the remaining time would be modeled as: // remaning_file_sizes / transfer_speed // + remaining_file_count * per_file_overhead // + remaining_chunked_file_sizes / chunked_reassembly_speed // with us estimating the three parameters in conjunction. // // But we currently only model the bandwidth and the files per // second independently, which leads to incorrect values. To slightly // mitigate this problem, we combine the two models depending on // which factor dominates (essentially big-file-upload vs. // many-small-files) // // If we have size information, we prefer an estimate based // on the upload speed. That's particularly relevant for large file // up/downloads, where files per second will be close to 0. // // However, when many *small* files are transfered, the estimate // can become very pessimistic as the transfered amount per second // drops significantly. // // So, if we detect a high rate of files per second or a very low // transfer rate (often drops hugely during a sequence of deletes, // for instance), we gradually prefer an optimistic estimate and // assume the remaining transfer will be done with the highest speed // we've seen. // Compute a value that is 0 when fps is <=L*max and 1 when fps is >=U*max double fps = _fileProgress._progressPerSec; double fpsL = 0.5; double fpsU = 0.8; double nearMaxFps = qBound(0.0, (fps - fpsL * _maxFilesPerSecond) / ((fpsU - fpsL) * _maxFilesPerSecond), 1.0); // Compute a value that is 0 when transfer is >= U*max and // 1 when transfer is <= L*max double trans = _sizeProgress._progressPerSec; double transU = 0.1; double transL = 0.01; double slowTransfer = 1.0 - qBound(0.0, (trans - transL * _maxBytesPerSecond) / ((transU - transL) * _maxBytesPerSecond), 1.0); double beOptimistic = nearMaxFps * slowTransfer; size.estimatedEta = (1.0 - beOptimistic) * size.estimatedEta + beOptimistic * optimisticEta(); return size; }
bool ProgressInfo::trustEta() const { return totalProgress().estimatedEta < 100 * optimisticEta(); }