2

我想按某些属性计算请求并按某个时间段(可能是秒)汇总它们,然后在最后 10 秒、最后 2 分钟等运行平均值/最大值/最小值。

显而易见的(对我来说)方法是只列出秒数,当我需要移动/运行平均值时,只需返回列表中适当的时间量并计算平均值。除了围绕存储聚合值以供较长时间使用的一些明显优化之外,我还缺少什么想法?

4

2 回答 2

7

我更喜欢exponential moving average它,因为它更简单并且不需要将值保存在数组中

这是我过去使用的功能

func MovingExpAvg(value, oldValue, fdtime, ftime float64) float64 {
  alpha := 1.0 - math.Exp(-fdtime/ftime)
  r := alpha * value + (1.0 - alpha) * oldValue
  return r
}

和代码示例

http://play.golang.org/p/OZ25cwKMnT

于 2012-09-22T08:23:22.383 回答
4

我对 Go 不是很熟悉,所以请原谅以下代码中的任何奇怪之处。向滚动平均值添加一个元素应该是 O(1) 的时间。它在内存中使用 O(n)(固定数量)。

package main

import "fmt"

func rolling(n int) func(float64) float64 {
        bins := make([]float64, n)
        average := 0.0
        i := 0
        return func(x float64) float64 {
                average += (x - bins[i]) / float64(n)
                bins[i] = x
                i = (i + 1) % n
                return average
        }
}

func main() {
        add := rolling(5)
        add(1)
        add(2)
        add(3)
        add(4)
        fmt.Println("(1+2+3+4+5          ) / 5 =", add(5))
        fmt.Println("(  2+3+4+5+9        ) / 5 =", add(9))
        fmt.Println("(    3+4+5+9+3      ) / 5 =", add(3))
        fmt.Println("(      4+5+9+3+0    ) / 5 =", add(0))
        fmt.Println("(        5+9+3+0-9  ) / 5 =", add(-9))
        fmt.Println("(          9+3+0-9-8) / 5 =", add(-8))
}

输出:

$ go run roll.go
(1+2+3+4+5          ) / 5 = 3
(  2+3+4+5+9        ) / 5 = 4.6
(    3+4+5+9+3      ) / 5 = 4.8
(      4+5+9+3+0    ) / 5 = 4.2
(        5+9+3+0-9  ) / 5 = 1.6
(          9+3+0-9-8) / 5 = -1
于 2012-09-22T00:49:10.090 回答