Add a rolling average of dl speed for time estimation

This commit is contained in:
Florian Bruhin 2014-06-13 21:53:06 +02:00
parent d80c05b0b1
commit 85ee71b739

View File

@ -19,6 +19,7 @@
import os import os
import os.path import os.path
from collections import deque
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
@ -37,6 +38,8 @@ class DownloadItem(QObject):
Class attributes: Class attributes:
SPEED_REFRESH_INTERVAL: How often to refresh the speed, in msec. SPEED_REFRESH_INTERVAL: How often to refresh the speed, in msec.
SPEED_AVG_WINDOW: How many seconds of speed data to average to
estimate the remaining time.
Attributes: Attributes:
reply: The QNetworkReply associated with this download. reply: The QNetworkReply associated with this download.
@ -47,6 +50,7 @@ class DownloadItem(QObject):
fileobj: The file object to download the file to. fileobj: The file object to download the file to.
filename: The filename of the download. filename: The filename of the download.
is_cancelled: Whether the download was cancelled. is_cancelled: Whether the download was cancelled.
speed_avg: A rolling average of speeds.
_last_done: The count of bytes which where downloaded when calculating _last_done: The count of bytes which where downloaded when calculating
the speed the last time. the speed the last time.
_last_percentage: The remembered percentage for data_changed. _last_percentage: The remembered percentage for data_changed.
@ -60,6 +64,7 @@ class DownloadItem(QObject):
""" """
SPEED_REFRESH_INTERVAL = 500 SPEED_REFRESH_INTERVAL = 500
SPEED_AVG_WINDOW = 30
data_changed = pyqtSignal() data_changed = pyqtSignal()
finished = pyqtSignal() finished = pyqtSignal()
error = pyqtSignal(str) error = pyqtSignal(str)
@ -77,6 +82,9 @@ class DownloadItem(QObject):
self.bytes_total = None self.bytes_total = None
self.speed = None self.speed = None
self.basename = '???' self.basename = '???'
samples = int(self.SPEED_AVG_WINDOW *
(1000 / self.SPEED_REFRESH_INTERVAL))
self.speed_avg = deque(maxlen=samples)
self.fileobj = None self.fileobj = None
self.filename = None self.filename = None
self.is_cancelled = False self.is_cancelled = False
@ -137,9 +145,11 @@ class DownloadItem(QObject):
def remaining_time(self): def remaining_time(self):
"""Property to get the remaining download time in seconds.""" """Property to get the remaining download time in seconds."""
if (self.bytes_total is None or self.bytes_total <= 0 or if (self.bytes_total is None or self.bytes_total <= 0 or
self.speed is None or self.speed == 0): self.speed is None or not self.speed_avg):
return None return None
return (self.bytes_total - self.bytes_done) / self.speed remaining_bytes = self.bytes_total - self.bytes_done
speed = sum(self.speed_avg) / len(self.speed_avg)
return remaining_bytes / speed
def bg_color(self): def bg_color(self):
"""Background color to be shown.""" """Background color to be shown."""
@ -267,7 +277,7 @@ class DownloadItem(QObject):
else: else:
delta = self.bytes_done - self._last_done delta = self.bytes_done - self._last_done
self.speed = delta * 1000 / self.SPEED_REFRESH_INTERVAL self.speed = delta * 1000 / self.SPEED_REFRESH_INTERVAL
logger.debug("Download speed: {} bytes/sec".format(self.speed)) self.speed_avg.append(self.speed)
self._last_done = self.bytes_done self._last_done = self.bytes_done
self.data_changed.emit() self.data_changed.emit()