我正在使用DescriptiveStatistics来跟踪某些指标的移动平均值。我有一个每分钟提交度量值的线程,我使用DescriptiveStatistics上的setWindowSize(10)
方法跟踪度量标准的10分钟移动平均值。
这适用于跟踪单个移动平均线,但我实际上需要跟踪多个移动平均线,即1分钟平均值,5分钟平均值和10分钟平均值。
目前我有以下选择:
拥有3个不同的DescriptiveStatistics实例和3个不同的窗口。但是,这意味着我们会多次存储原始指标,这是不理想的。
拥有一个DescriptiveStatistics实例,并在查询移动平均线时执行以下操作:
int minutes = <set from parameter>;
DescriptiveStatistics stats = <class variable>;
if (minutes == stats.getN()) return stats.getMean();
SummaryStatistics subsetStats = new SummaryStatistics();
for (int i = 0; i < minutes; i++) {
subsetStats.addValue(stats.getElement((int)stats.getN() - i - 1));
}
return subsetStats.getMean();
但是,选项2意味着每次查询窗口小于DescriptiveStats窗口大小的移动平均值时,我都必须重新计算一堆平均值。
有没有办法更好地做到这一点?我希望存储1个度量数据副本,并以不同的间隔连续计算它的N个移动平均值。这可能会进入Codahale Metrics或Netflix Servo的土地,但我不想仅仅为了这个而使用重量级的库。
答案 0 :(得分:1)
您可以使用StatUtils
实用程序类并在添加新值时管理数组。另一种方法是使用大小为10的CircularFifoQueue
StatUtils
和Apache Utils来简化向原始值数组的转换。
您可以在Apache Commons中找到CircularFifoQueue<Double> queue = new CircularFifoQueue<>(10);
// Add your values
double[] values = ArrayUtils.toPrimitive(queue.toArray(new Double[0]))
mean1 = StatUtils.mean(values, 0, 1);
mean5 = StatUtils.mean(values, 0, 5);
mean10 = StatUtils.mean(values, 0, 10);
的示例,以下内容与您的用例类似。
'idp' => array (
'entityId' => 'https://app.onelogin.com/saml/metadata/123456',
'singleSignOnService' => array (
'url' => 'https://app.onelogin.com/trust/saml2/http-post/sso/123456',
),
'singleLogoutService' => array (
'url' => 'https://app.onelogin.com/trust/saml2/http-redirect/slo/123456',
),
'x509cert' => 'XXXXxXXX1xXxXXXxXXXXXXxXXxxXx...',
)