Para un rendimiento óptimo, probablemente solo pueda utilizar una serie de largos en lugar de una lista.
Tuvimos un requisito similar en un punto para implementar un estimador de tiempo de descarga, y utilizamos un buffer circular para almacenar la velocidad sobre cada uno de los últimos N
segundos.
No nos interesaba la velocidad de la descarga durante todo el tiempo, aproximadamente el tiempo que se esperaba según la actividad reciente, pero no por lo que reciente las cifras estarían saltando por todas partes (como si hubiéramos usado el último segundo para calcularlo).
La razón por la que no estábamos interesados en el intervalo de tiempo completo fue que una descarga podría ser de 1M/s durante media hora y luego cambiar a 10M/s durante los siguientes diez minutos. Esa primera media hora arrastrará la velocidad promedio bastante severamente, a pesar de que ahora está descargando bastante rápido.
Creamos un búfer circular con cada celda conteniendo la cantidad descargada en un período de 1 segundo. El tamaño del búfer circular era 300, lo que permite 5 minutos de datos históricos, y cada celda se inicializó a cero. En su caso, solo necesitaría diez celdas.
También mantuvimos un total (la suma de todas las entradas en el búfer, así que también inicialmente cero) y el recuento (inicialmente cero, obviamente).
Cada segundo, queremos averiguar cómo se habían descargado la cantidad de datos desde el último segundo y luego:
- restar la celda actual del total.
- ponga la cifra actual en esa celda y avance el puntero de la celda.
- suma esa cifra actual al total.
- aumentar el recuento si no era ya 300.
- actualizar la figura que se muestra al usuario, en función del total/recuento.
Básicamente, en pseudo-código:
def init (sz):
buffer = new int[sz]
for i = 0 to sz - 1:
buffer[i] = 0
total = 0
count = 0
index = 0
maxsz = sz
def update (kbps):
total = total - buffer[index] + kbps # Adjust sum based on deleted/inserted values.
buffer[index] = kbps # Insert new value.
index = (index + 1) % maxsz # Update pointer.
if count < maxsz: # Update count.
count = count + 1
return total/count # Return average.
Eso debería ser fácilmente adaptable a sus propios requisitos. La suma es una buena característica para "caché" de información que puede hacer que su código sea aún más rápido. Con eso quiero decir: si necesita calcular la suma o el promedio, puede resolverlo solo cuando los datos cambien y utilizando los cálculos mínimos necesarios.
La alternativa sería una función que sumara los diez números cuando se solicite, algo que sería más lento que el simple restar o agregar al cargar otro valor en el búfer.
¿Qué pasa con el uso del generador de perfiles? –
@Brandon, planeo usar el valor promediado para mostrar a los usuarios, como un indicador de cuánto tiempo está tomando el análisis de un objeto. Esto es parte de una utilidad de traducción gráfica. – JYelton