2012-01-15 12 views
6

Tengo una aplicación que, mientras se realiza una tarea en segundo plano, muestra una barra de progreso con un cálculo del "tiempo restante estimado" (por ejemplo, "5 segundos restantes") y un "tiempo estimado de finalización" (por ejemplo, "completa a las 12:59 : 59 "), o como yo lo llamo, la ETA.¿Cómo puedo eliminar el "jitter" de mi cálculo de "tiempo estimado restante" (y ETA)?

El algoritmo para calcular esta ETA básicamente toma el "promedio móvil" de progreso en el tiempo:
1. Cada evento de progreso se agrega a una cola con la hora actual.
2. Después de una cierta duración (por ejemplo, 10 s), los elementos se eliminan de la cola.
3. La ETA se extrapola del primer y último elemento de la cola.
El código fuente está disponible si se preocupan: ETACalculator.cs

Sin embargo, hay un problema fluctuación. A medida que se agrega cada evento de progreso al cálculo, la ETA se actualizará ligeramente. Digamos que la ETA cambia solo por 0.1s. Este pequeño jitter fácilmente causa que el ETA "revolotee". Por ejemplo, en lugar de ver una progresión suave desde 5s, 4s, 3s, etc ..., veo 5-5-5-4-5-4-5-4-5-4-4-4.

Estaba pensando simplemente en reducir las actualizaciones a 1 por segundo, pero luego la barra de progreso es menos uniforme, y también me gustaría que las ralentizaciones "reales" se muestren en tiempo real.

Tengo problemas para encontrar un algoritmo simple que reduzca esta inestabilidad. ¿Cómo puedo eliminar el jitter?

+0

¿Winforms? WPF? ¿Algo más? ¿Puedes publicar el código relevante? – Oded

+3

Obligatorio [referencia xkcd] (http://xkcd.com/612/). – Ani

+0

Actualice el progreso solo si se reduce. (es decir, no vuelva a cambiar a 5 si actualmente estamos en 4). –

Respuesta

9

independiente del progreso real nerviosos y la muestra el progreso en dos variables separadas.

Actualice el progreso nervioso como lo hace ahora.

En un intervalo regular (relativamente rápido), actualice el progreso mostrado a acercamiento al progreso real.

Un algoritmo de enfoque simple sería la de la media de los dos valores

display_progress = (display_progress + actual_progress)/2 

Esto amortiguar el valor para reflejar los valores del pasado y no sólo el valor inmediato.

También puede reducir la suavidad mediante el uso de:

display_progress = (P) * display_progress + (1.0-P) * actual_progress 

Dónde P es un valor constante entre 0.0 y 1.0.

Editar:

Este es uno de los muchos filtros que podrían ser utilizados. Este es bueno ya que no requiere mucha contabilidad.

Sin embargo, conseguir salida perfecta no va a ser una opción, debido a que el defecto está en su entrada. La diferencia entre "jitter" y "ralentizaciones reales" solo es observable después de que sucedió.

+1

Buena idea (un filtro de paso bajo IIR de primer orden), pero esto debe hacerse en la variable "tiempo restante", no en la variable "% progreso". –

+0

Puedo ver cómo esto "suavizará" el progreso, y podría ser una buena adición a mi cálculo de progreso. Pero creo que esto todavía sufrirá la inestabilidad en la extrapolación de ETA. Incluso si el jitter es solo '0,00001', eso aparecerá cuando el ETA esté entre' 5,00000' y '4,99999'. Lo siento, mi pregunta no dejó esto en claro; Voy a actualizarlo. –

2

No es muy claro en su algoritmo sin ver el código, pero cuando actualiza su ETA solo primero compruebe la ETA actual y solo la actualice si el nuevo valor es menor que el anterior.

+1

Actualicé con un enlace a [ETACalculator.cs] (https://github.com/scottrippey/Progression/blob/master/Progression/Extras/ETACalculator.cs), si estás interesado. Sin embargo, en mi situación, el progreso puede ralentizarse, en cuyo caso quiero mostrar una ETA precisa. –

Cuestiones relacionadas