web-dev-qa-db-fra.com

Comment estimer le temps de téléchargement restant (avec précision)?

Bien sûr, vous pouvez diviser la taille du fichier restant par la vitesse de téléchargement actuelle, mais si votre vitesse de téléchargement fluctue (et ce sera le cas), cela ne produira pas un très bon résultat. Qu'est-ce qu'un meilleur algorithme pour produire des comptes à rebours plus lisses?

56
mpen

Il y a des années, j'ai écrit un algorithme pour prédire le temps restant dans un programme de multidiffusion et d'imagerie de disque utilisant une moyenne mobile avec une réinitialisation lorsque le débit actuel dépassait une plage prédéfinie. Cela maintiendrait les choses en douceur à moins que quelque chose de grave ne se produise, puis il s'ajusterait rapidement pour revenir ensuite à une moyenne mobile. Voir exemple de graphique ici:

 enter image description here

La ligne bleue épaisse dans cet exemple de graphique représente le débit réel dans le temps. Notez le faible débit au cours de la première moitié du transfert, puis il augmente considérablement au cours de la seconde moitié. La ligne orange est une moyenne globale. Notez qu’elle ne s’ajuste jamais assez loin pour permettre de prédire avec exactitude le temps qu’il faudra pour terminer. La ligne grise est une moyenne mobile (c’est-à-dire la moyenne des N derniers points de données - dans ce graphique, N est égal à 5, mais en réalité, il pourrait être nécessaire que N soit plus grand pour être suffisamment lisse). Il récupère plus rapidement, mais il faut encore un certain temps pour s’adapter. Il faudra plus de temps si le plus grand N est. Donc, si vos données sont assez bruyantes, alors N devra être plus grand et le temps de récupération sera plus long.

La ligne verte est l'algorithme que j'ai utilisé. Il fonctionne comme une moyenne mobile, mais lorsque les données se déplacent en dehors d'une plage prédéfinie (désignée par les lignes bleues et jaunes très fines), il réinitialise la moyenne mobile et saute immédiatement. La plage prédéfinie peut également être basée sur la déviation standard afin de pouvoir ajuster automatiquement le niveau de bruit des données. Je viens de jeter ces valeurs dans Excel pour les représenter dans cette représentation, donc ce n’est pas parfait, mais vous voyez l’idée.

Les données pourraient être conçues pour que cet algorithme ne soit pas un bon prédicteur du temps restant. En fin de compte, vous devez avoir une idée générale du comportement des données et choisir un algorithme en conséquence. Mon algorithme fonctionnait bien pour les ensembles de données que je voyais. Nous avons donc continué à l'utiliser.

Un autre conseil important est que les développeurs ignorent généralement les temps de configuration et de démontage dans leurs barres de progression et leurs calculs d'estimation de temps. Il en résulte une barre de progression éternelle de 99% ou 100% qui reste là pendant une longue période (pendant le vidage des caches ou un autre travail de nettoyage) ou des premières estimations démesurées lors de l'analyse de répertoires ou d'un autre travail d'installation mais n'accumulant aucun pourcentage de progrès, ce qui jette tout. Vous pouvez exécuter plusieurs tests incluant les temps de configuration et de démontage et proposer une estimation de la durée moyenne de ces temps, ou en fonction de la taille du travail, et l'ajouter à la barre de progression. Par exemple, les premiers 5% du travail sont des travaux d’installation, les 10% restants sont des travaux de démontage, puis les 85% au milieu correspondent au téléchargement ou à tout autre processus de répétition de votre suivi. Cela peut aider beaucoup aussi.

7
rcronk

Une moyenne mobile exponentielle est idéale pour cela. Cela permet de lisser votre moyenne de sorte que, chaque fois que vous ajoutez un nouvel échantillon, les anciens échantillons deviennent de moins en moins importants pour la moyenne globale. Ils sont toujours pris en compte, mais leur importance diminue de manière exponentielle - d'où son nom. Et comme il s'agit d'une moyenne "mobile", il vous suffit de garder un seul chiffre autour.

Dans le contexte de la mesure de la vitesse de téléchargement, la formule ressemblerait à ceci:

averageSpeed = SMOOTHING_FACTOR * lastSpeed + (1-SMOOTHING_FACTOR) * averageSpeed;

SMOOTHING_FACTOR est un nombre compris entre 0 et 1. Plus ce nombre est élevé, plus les échantillons les plus anciens sont supprimés rapidement. Comme vous pouvez le constater dans la formule, lorsque SMOOTHING_FACTOR vaut 1, vous utilisez simplement la valeur de votre dernière observation. Lorsque SMOOTHING_FACTOR est 0 averageSpeed ne change jamais. Donc, vous voulez quelque chose entre les deux, et généralement une valeur faible pour obtenir un lissage décent. J'ai constaté que 0,005 offre une valeur de lissage assez bonne pour une vitesse de téléchargement moyenne.

lastSpeed est la dernière vitesse de téléchargement mesurée. Vous pouvez obtenir cette valeur en exécutant une minuterie toutes les secondes environ afin de calculer le nombre d'octets téléchargés depuis la dernière fois que vous l'avez exécutée.

averageSpeed est évidemment le nombre que vous souhaitez utiliser pour calculer votre temps restant estimé. Initialisez ceci à la première mesure lastSpeed que vous obtenez.

112
Ben Dolman
speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2
7
TiansHUo

Je pense que le mieux que vous puissiez faire est de diviser la taille du fichier restant par la vitesse de téléchargement moyenne (jusqu'à présent divisée par le temps que vous avez téléchargé). Cela fluctuera un peu au début mais sera de plus en plus stable au fur et à mesure que vous téléchargez.

5
Andreas Brinck

Dans le prolongement de la réponse de Ben Dolman, vous pouvez également calculer la fluctuation au sein de l'algorithme. Ce sera plus lisse, mais cela prédira également la vitesse moyenne.

Quelque chose comme ça:

prediction = 50;
depencySpeed = 200;
stableFactor = .5;
smoothFactor = median(0, abs(lastSpeed - averageSpeed), depencySpeed);
smoothFactor /= (depencySpeed - prediction * (smoothFactor / depencySpeed));
smoothFactor = smoothFactor * (1 - stableFactor) + stableFactor;
averageSpeed = smoothFactor * lastSpeed + (1 - smoothFactor) * averageSpeed;

Fluctuation ou non, elle sera aussi stable que l’autre, avec les bonnes valeurs pour la prédiction et le depencySpeed; vous devez jouer avec cela un peu en fonction de votre vitesse Internet . Ces réglages sont parfaits pour une vitesse moyenne de 600 ko/s alors qu’elle varie de 0 à 1 Mo.

2
Tim

J'ai trouvé la réponse de Ben Dolman très utile, mais pour quelqu'un comme moi qui n'aime pas les maths, il m'a fallu environ une heure pour l'intégrer pleinement dans mon code. Voici un moyen plus simple de dire la même chose en python. S'il y a des imprécisions, dites-le-moi, mais dans mes tests, cela fonctionne très bien:

def exponential_moving_average(data, samples=0, smoothing=0.02):
    '''
    data: an array of all values.
    samples: how many previous data samples are avraged. Set to 0 to average all data points.
    smoothing: a value between 0-1, 1 being a linear average (no falloff).
    '''

    if len(data) == 1:
        return data[0]

    if samples == 0 or samples > len(data):
        samples = len(data)

    average = sum(data[-samples:]) / samples
    last_speed = data[-1]
    return (smoothing * last_speed) + ((1 - smoothing) * average)

input_data = [4.5, 8.21, 8.7, 5.8, 3.8, 2.7, 2.5, 7.1, 9.3, 2.1, 3.1, 9.7, 5.1, 6.1, 9.1, 5.0, 1.6, 6.7, 5.5, 3.2] # this would be a constant stream of download speeds as you go, pre-defined here for illustration

data = []
ema_data = []

for sample in input_data:
    data.append(sample)
    average_value = exponential_moving_average(data)
    ema_data.append(average_value)

# print it out for visualization
for i in range(len(data)):
    print("REAL: ", data[i])
    print("EMA:  ", ema_data[i])
    print("--")
0
Spencer