计算每秒字节数(平滑的方式)

Rie*_*u͢s 7 javascript design-patterns file-upload

我正在寻找一种解决方案来计算重复调用的每秒传输字节数function(下图).由于它的不准确,我希望简单地除以经过的总时间的传输的字节:它造成了无法几分钟后运行,显示速度快的变化.

预设(大约每隔50ms调用一次):

function uploadProgress(loaded, total){
    var bps = ?;
    $('#elem').html(bps+' bytes per second');
};
Run Code Online (Sandbox Code Playgroud)
  • 如何(仅)获得最后n几秒的平均每秒字节数,这是一个好主意吗?
  • 还有哪些其他用于计算非闪烁但精确的bps值的实践?

Gro*_*roo 9

你的第一个想法是坏的,它被称为移动平均线,并且你可以定期调用你的更新函数你只需要保留一个队列(一个FIFO缓冲区)一个恒定长度):

var WINDOW_SIZE = 10;
var queue = [];

function updateQueue(newValue) {
    // fifo with a fixed length
    queue.push(newValue);
    if (queue.length > WINDOW_SIZE)
        queue.shift();
}

function getAverageValue() {

    // if the queue has less than 10 items, decide if you want to calculate
    // the average anyway, or return an invalid value to indicate "insufficient data"

    if (queue.length < WINDOW_SIZE) {

        // you probably don't want to throw if the queue is empty, 
        // but at least consider returning an 'invalid' value in order to
        // display something like "calculating..."

        return null;
    }

    // calculate the average value
    var sum = 0;
    for (var i = 0; i < queue.length; i++) {
        sum += queue[i];
    }
    return sum / queue.length;
}

// calculate the speed and call `updateQueue` every second or so
var updateTimer = setInterval(..., 1000);
Run Code Online (Sandbox Code Playgroud)

避免计算速度突然变化的更简单方法是使用低通滤波器.PT1滤波器的简单离散近似是:

离散PT1滤波器近似

其中u[k]是输入(或实际值在样品)k,y[k]是输出(或滤波后的值在样品)k,并且T是时间常数(较大的T那个装置y将遵循u更慢).

那会被翻译成:

var speed = null;
var TIME_CONSTANT = 5;

function updateSpeed(newValue) {    
    if (speed === null) {
        speed = newValue;
    } else {
        speed += (newValue - speed) / TIME_CONSTANT;
    }
}

function getFilteredValue() {
    return speed;
}
Run Code Online (Sandbox Code Playgroud)

两种解决方案都会给出类似的结果(至少为了你的目的),而后者似乎更简单(并且需要更少的内存).

另外,我不会快速更新值.过滤只会以50ms的刷新率将"闪烁"变为"摆动".我认为没有人希望以每秒一次(甚至几秒钟)的刷新率显示上传速度.