Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 每秒计算字节数(平滑方式)_Javascript_Design Patterns_File Upload - Fatal编程技术网

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

Javascript 每秒计算字节数(平滑方式),javascript,design-patterns,file-upload,Javascript,Design Patterns,File Upload,我正在寻找一种解决方案来计算重复调用的函数的每秒传输字节数(见下文)。由于其不精确性,我不想简单地将传输的字节除以经过的总时间:这导致运行几分钟后无法显示快速的速度变化 预设值(大约每50毫秒调用一次): 如何获得(仅)最后n秒的平均每秒字节数,这是一个好主意吗 计算不闪烁但精确的bps值的其他做法有哪些 使用衰减平均值,则不必保留旧值 更新:基本上是这样一个公式: average = new_value * factor + average_old * (100 - factor); 您不

我正在寻找一种解决方案来计算重复调用的
函数的每秒传输字节数(见下文)。由于其不精确性,我不想简单地将传输的字节除以经过的总时间:这导致运行几分钟后无法显示快速的速度变化

预设值(大约每50毫秒调用一次):

  • 如何获得(仅)最后
    n
    秒的平均每秒字节数,这是一个好主意吗
  • 计算不闪烁但精确的bps值的其他做法有哪些

使用衰减平均值,则不必保留旧值

更新:基本上是这样一个公式:

average = new_value * factor + average_old * (100 - factor);
您不必保留任何旧的值,它们都以越来越小的比例存在。您必须为因子选择一个适合于您想要的新旧值组合的值,以及平均值更新的频率


我相信这就是Unix“平均负载”的计算方法。

您的第一个想法不错,它被称为a,如果您定期调用更新函数,您只需要保持一个恒定长度的队列(a):

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);
两种解决方案都会给出类似的结果(至少对您来说是这样),而后一种解决方案似乎更简单(并且需要更少的内存)


而且,我不会更新值那么快。过滤只会以50毫秒的刷新率将“闪烁”变为“摆动”。我认为没有人希望上传速度以每秒超过一次(甚至几秒钟)的刷新率显示。

一个简单的低通过滤器可以确保不会出现错误。但是,如果您对测量传输速率有更深入的思考,您就需要维护单独的整数计数器来正确地进行测量

如果您希望它是一个精确的计数,请注意,有一个简化可用。首先,在处理速率时,将它们的算术平均值应用于字节/秒是错误的(秒/字节更正确-这会导致调和平均值)。另一个问题是它们应该加权。正因为如此,简单地保持int64运行字节总数与观察时间的对比实际上是正确的——听起来很愚蠢。通常情况下,每个w的权重为1/n。看一看当你按时间称重时发生的简洁简化:

(w0*b0/t0+w1*b1/t1+w2*b2/t2+…)/(w0+w1+w2+…)

总字节/总重量

(b0+b1+b2+…)/(w0+w1+w2+…)

所以只需将字节和毫秒的总数分开(int64!)。并仅将其作为渲染步骤进行划分,以可视化速率。请注意,如果您使用调和平均值(对于速率,您应该这样做,因为您实际上是在平均秒/字节),那么这与发送一个字节所需的时间相同,由字节数加权

1/((w0*t0/b0+w1*t1/b0+…)/(w0+w1+w2+…)= 总字节/总时间

所以按时间加权的算术平均数和按字节加权的调和平均数是一样的。只需在一个变量中保持字节总数,在另一个变量中保持时间。还有一个更深层次的原因,就是这种简单化的计算实际上是正确的。想想积分。假设没有并发,这实际上就是传输的总字节数除以总观察时间。假设计算机实际上每毫秒执行1步,只发送整个字节,并且您观察整个时间间隔时没有间隔。没有近似值

请注意,如果考虑以(msec,byte/msec)作为(x,y)单位的整数,则曲线下的区域就是观察期间发送的字节(准确地说)。无论观察结果如何被分割,你都会得到相同的答案。(即:报告频率为2倍)

因此,通过简单地报告(大小字节、开始字节、停止字节),您只需将(停止字节-开始字节)累积到时间中,并累积每个观测值的大小字节。如果您想将这些速率划分为以分钟为单位的图表,那么只需维护每分钟(观察值)的(字节,毫秒)对即可

请注意,这些是个人转账的经验费率。单个传输可能会经历1MB/s(用户角度)。这些是您向最终用户保证的费率

对于简单的情况,您可以把它放在这里。但是正确地计算,会带来更多有趣的事情

从服务器的角度来看,负载很重要。假设有两个用户同时体验1MB/s。对于这个统计,你需要减去重复计算的时间。如果两个用户同时在1s内运行1MB/s,则在1s内运行2MB/s。您需要有效地重建时间重叠,并减去重复计算的时间段。在传输结束时显式记录(大小字节、开始时间、停止时间)允许您测量有趣的内容:

  • 任何给定时间内未完成的传输数(队列长度分布-即:“我是否将耗尽内存?”)
  • 吞吐量是传输次数的函数(队列长度的吞吐量-即:“当我们的广告在电视上播放时,网站会崩溃吗?”)
  • 利用率-即:“我们是否向云提供商支付过高的费用?”

在这种情况下,所有累加计数器都是精确的整数运算。减去重复计算的时间会让你突然陷入更复杂的算法中(高效实时计算)。

你可能在寻找移动平均线之类的东西,这意味着您需要跟踪时间序列数据。您从何处获取数据?@MattBall所以您说我应该每秒保存接收到的字节,然后计算最后n秒的平均值?尖刻:这些数字来自一个我拿不到的上传脚本,以防你要求额外的数据
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);
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;
}