目标
- 维护一段win时间内的三个best最大值或者最小值,以最大值为例
- 值大小上,1st best > 2nd best > 3rd best
-
采集时间,1st best < 2nd best < 3rd best
注:win时间,表示一个窗口时间,或者说一段时间
代码分析
以最大值为例进行分析
基本结构体
一个样本,包含一个时间值和一个大小,其中时间值没有单位,由调用者决定,只要保证和win时间的单位一致即可,所以可以是秒,可以是10s
/* A single data point for our parameterized min-max tracker */
struct minmax_sample {
u32 t; /* time measurement was taken */
u32 v; /* value measured */
};
状态跟踪结构体,三个样本
/* State for the parameterized min-max tracker */
struct minmax {
struct minmax_sample s[3];
};
重置
static inline u32 minmax_reset(struct minmax *m, u32 t, u32 meas)
{
struct minmax_sample val = { .t = t, .v = meas };
m->s[2] = m->s[1] = m->s[0] = val;
return m->s[0].v;
}
将三个best值全部设置为传入的时间值和样本值。
更新最大值
/* Check if new measurement updates the 1st, 2nd or 3rd choice max. */
u32 minmax_running_max(struct minmax *m, u32 win, u32 t, u32 meas)
{
struct minmax_sample val = { .t = t, .v = meas };
if (unlikely(val.v >= m->s[0].v) || /* found new max? */
unlikely(val.t - m->s[2].t > win)) /* nothing left in window? */
return minmax_reset(m, t, meas); /* forget earlier samples */
if (unlikely(val.v >= m->s[1].v))
m->s[2] = m->s[1] = val;
else if (unlikely(val.v >= m->s[2].v))
m->s[2] = val;
return minmax_subwin_update(m, win, &val);
}
用流程图表示:
刷新时间
/* As time advances, update the 1st, 2nd, and 3rd choices. */
static u32 minmax_subwin_update(struct minmax *m, u32 win,
const struct minmax_sample *val)
{
u32 dt = val->t - m->s[0].t;
if (unlikely(dt > win)) {
/*
* Passed entire window without a new val so make 2nd
* choice the new val & 3rd choice the new 2nd choice.
* we may have to iterate this since our 2nd choice
* may also be outside the window (we checked on entry
* that the third choice was in the window).
*/
m->s[0] = m->s[1];
m->s[1] = m->s[2];
m->s[2] = *val;
if (unlikely(val->t - m->s[0].t > win)) {
m->s[0] = m->s[1];
m->s[1] = m->s[2];
m->s[2] = *val;
}
} else if (unlikely(m->s[1].t == m->s[0].t) && dt > win/4) {
/*
* We've passed a quarter of the window without a new val
* so take a 2nd choice from the 2nd quarter of the window.
*/
m->s[2] = m->s[1] = *val;
} else if (unlikely(m->s[2].t == m->s[1].t) && dt > win/2) {
/*
* We've passed half the window without finding a new val
* so take a 3rd choice from the last half of the window
*/
m->s[2] = *val;
}
return m->s[0].v;
}
用流程图表示:
有几个问题
- 为什么更新两次全部更新之后不再比较3rd与样本值?
- 因为在更新最大值的第一步流程中就比较过新样本和3rdbest的时间戳,所以这里保证了3rdbest的时间戳和样本的时间戳差值肯定在win时间内
- 如果2nd的值未设置过,则需要等待win的0.25倍时间
- 如果3rd的值未设置过,则需要等待win的0.5倍时间
总结
- win_minmax维护了win时间内的最优值
- 当1st best已经不属于当前时间的win窗口时间内时,会由2nd best顶上,甚至3rd best顶上
————-
探花原创
版权声明:本文为weixin_45490038原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。