¿Cómo estimar el tiempo de descarga restante (con precisión)?

Claro que podría dividir el tamaño del archivo restante por la velocidad de descarga actual, pero si la velocidad de descarga fluctúa (y lo hará), esto no produce un resultado muy bueno. ¿Cuál es un mejor algoritmo para producir cuentas regresivas más suaves?

Hace años, escribí un algoritmo para predecir el tiempo restante en un progtwig de imágenes y multidifusión de disco que usaba un promedio móvil con un reinicio cuando el rendimiento actual salía de un rango predefinido. Mantendría las cosas sin problemas a menos que sucediera algo drástico, luego se ajustaría rápidamente y luego volvería a una media móvil nuevamente. Vea el cuadro de ejemplo aquí:

enter image description here

La línea azul gruesa en ese gráfico de ejemplo es el rendimiento real en el tiempo. Observe el bajo rendimiento durante la primera mitad de la transferencia y luego salta dramáticamente en la segunda mitad. La línea naranja es un promedio general. Tenga en cuenta que nunca se ajusta lo suficiente como para dar una predicción precisa de cuánto tardará en terminar. La línea gris es un promedio móvil (es decir, el promedio de los últimos N puntos de datos; en este gráfico, N es 5, pero en realidad, N podría necesitar ser más grande para suavizarse lo suficiente). Se recupera más rápido, pero aún tarda un tiempo en ajustarse. Llevará más tiempo que el N más grande. Entonces, si sus datos son bastante ruidosos, entonces N tendrá que ser más grande y el tiempo de recuperación será más largo.

La línea verde es el algoritmo que utilicé. Va de la misma manera que una media móvil, pero cuando los datos se mueven fuera de un rango predefinido (designado por las líneas azul claro y amarillo claro), restablece la media móvil y salta inmediatamente. El rango predefinido también se puede basar en la desviación estándar para que pueda ajustarse a la forma en que los datos son ruidosos automáticamente. Acabo de lanzar estos valores a Excel para diagtwigrlos para esta respuesta, por lo que no es perfecto, pero entiendes la idea.

Sin embargo, se podrían idear datos para hacer que este algoritmo no sea un buen predictor del tiempo restante. La conclusión es que debe tener una idea general de cómo espera que se comporten los datos y elegir un algoritmo en consecuencia. Mi algoritmo funcionó bien para los conjuntos de datos que estaba viendo, así que seguimos usándolo.

Otro consejo importante es que, por lo general, los desarrolladores ignoran los tiempos de instalación y desassembly en sus barras de progreso y los cálculos de estimación de tiempo. Esto da como resultado la eterna barra de progreso del 99% o 100% que permanece ahí durante mucho tiempo (mientras se vacían los cachés o se realizan otros trabajos de limpieza) o estimaciones iniciales desenfrenadas cuando se realiza el escaneo de directorios u otras tareas de configuración, acumulando tiempo pero no acumula ningún progreso porcentual, lo cual arroja todo. Puede ejecutar varias pruebas que incluyen los tiempos de instalación y desassembly y obtener una estimación de cuánto tiempo son en promedio o según el tamaño del trabajo y agregar ese tiempo a la barra de progreso. Por ejemplo, el primer 5% de trabajo es trabajo de configuración y el último 10% es trabajo de desassembly y luego el 85% en el medio es la descarga o el proceso de repetición que sigue su seguimiento. Esto puede ayudar mucho también.

Una media móvil exponencial es excelente para esto. Proporciona una forma de suavizar su promedio, de modo que cada vez que agrega una nueva muestra, las muestras antiguas se vuelven cada vez más importantes para el promedio general. Todavía se consideran, pero su importancia cae exponencialmente, de ahí el nombre. Y dado que es un promedio “en movimiento”, solo tiene que mantener un solo número alrededor.

En el contexto de la medición de la velocidad de descarga, la fórmula se vería así:

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

SMOOTHING_FACTOR es un número entre 0 y 1. Cuanto mayor sea este número, más rápido se descartarán las muestras antiguas. Como puede ver en la fórmula, cuando SMOOTHING_FACTOR es 1, simplemente está utilizando el valor de su última observación. Cuando SMOOTHING_FACTOR es 0 averageSpeed nunca cambia. Entonces, quiere algo intermedio, y generalmente un valor bajo para obtener un alisamiento decente. Descubrí que 0.005 proporciona un valor de suavizado bastante bueno para una velocidad de descarga promedio.

lastSpeed es la última velocidad de descarga medida. Puede obtener este valor ejecutando un temporizador cada segundo para calcular cuántos bytes ha descargado desde la última vez que lo ejecutó.

averageSpeed es, obviamente, el número que desea utilizar para calcular su tiempo restante estimado. Inicialice esto en la primera medición de lastSpeed que obtenga.

 speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2 

Creo que lo mejor que puedes hacer es dividir el tamaño del archivo restante entre la velocidad promedio de descarga (descargada hasta el momento dividida con el tiempo que has estado descargando). Esto fluctuará un poco para comenzar, pero será más y más estable cuanto más tiempo tarde en descargar.

En extensión a la respuesta de Ben Dolman, también se puede calcular la fluctuación dentro del algoritmo. Será más suave, pero también predecirá la velocidad de avance.

Algo como esto:

 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; 

Fluctuación o no, será tan estable como el otro, con los valores correctos para la predicción y la velocidad de dependencia; tienes que jugar con eso un poco dependiendo de tu velocidad de internet. Esta configuración es perfecta para una velocidad de 600 kB / s mientras fluctúa de 0 a 1 MB.