8366809: JFR: Use factory for aggregator functions

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2025-09-23 14:53:04 +00:00
parent fd30ae988b
commit 4df04a2543
3 changed files with 38 additions and 30 deletions

View File

@ -33,6 +33,7 @@ import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.internal.query.Configuration.Truncate;
import jdk.jfr.internal.query.Query.Grouper;
import jdk.jfr.internal.query.Query.OrderElement;
import jdk.jfr.internal.query.Function.FunctionFactory;
/**
* Field is the core class of the package.
@ -137,6 +138,8 @@ final class Field {
public int precision = -1;
public FunctionFactory functionFactory;
public Field(FilteredType type, String name) {
this.type = type;
this.name = name;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,45 +35,49 @@ import java.util.Set;
abstract class Function {
interface FunctionFactory {
Function newFunction();
}
public abstract void add(Object value);
public abstract Object result();
public static Function create(Field field) {
public static FunctionFactory createFactory(Field field) {
Aggregator aggregator = field.aggregator;
if (field.grouper != null || aggregator == Aggregator.MISSING) {
return new FirstNonNull();
return () -> new FirstNonNull();
}
if (aggregator == Aggregator.LIST) {
return new Container(new ArrayList<>());
return () -> new Container(new ArrayList<>());
}
if (aggregator == Aggregator.SET) {
return new Container(new LinkedHashSet<>());
return () -> new Container(new LinkedHashSet<>());
}
if (aggregator == Aggregator.DIFFERENCE) {
if (field.timestamp) {
return new TimeDifference();
return () -> new TimeDifference();
} else {
return new Difference();
return () -> new Difference();
}
}
if (aggregator == Aggregator.STANDARD_DEVIATION) {
if (field.timespan) {
return new TimespanFunction(new StandardDeviation());
return () -> new TimespanFunction(new StandardDeviation());
} else {
return new StandardDeviation();
return () -> new StandardDeviation();
}
}
if (aggregator == Aggregator.MEDIAN) {
if (field.timespan) {
return new TimespanFunction(new Median());
return () -> new TimespanFunction(new Median());
} else {
return new Median();
return () -> new Median();
}
}
@ -83,7 +87,6 @@ abstract class Function {
if (aggregator == Aggregator.P95) {
return createPercentile(field, 0.95);
}
if (aggregator == Aggregator.P99) {
return createPercentile(field, 0.99);
@ -92,46 +95,46 @@ abstract class Function {
return createPercentile(field, 0.999);
}
if (aggregator == Aggregator.MAXIMUM) {
return new Maximum();
return () -> new Maximum();
}
if (aggregator == Aggregator.MINIMUM) {
return new Minimum();
return () -> new Minimum();
}
if (aggregator == Aggregator.SUM) {
if (field.timespan) {
return new SumDuration();
return () -> new SumDuration();
}
if (field.fractionalType) {
return new SumDouble();
return () -> new SumDouble();
}
if (field.integralType) {
return new SumLong();
return () -> new SumLong();
}
}
if (aggregator == Aggregator.FIRST) {
return new First();
return () -> new First();
}
if (aggregator == Aggregator.LAST_BATCH) {
return new LastBatch(field);
return () -> new LastBatch(field);
}
if (aggregator == Aggregator.LAST) {
return new Last();
return () -> new Last();
}
if (aggregator == Aggregator.AVERAGE) {
if (field.timespan) {
return new AverageDuration();
return () -> new AverageDuration();
} else {
return new Average();
return () -> new Average();
}
}
if (aggregator == Aggregator.COUNT) {
return new Count();
return () -> new Count();
}
if (aggregator == Aggregator.UNIQUE) {
return new Unique();
return () -> new Unique();
}
return new Null();
return () -> new Null();
}
// **** AVERAGE ****
@ -507,12 +510,11 @@ abstract class Function {
}
// **** PERCENTILE ****
private static Function createPercentile(Field field, double percentile) {
Percentile p = new Percentile(percentile);
private static FunctionFactory createPercentile(Field field, double percentile) {
if (field.timespan) {
return new TimespanFunction(p);
return () -> new TimespanFunction(new Percentile(percentile));
} else {
return p;
return () -> new Percentile(percentile);
}
}

View File

@ -122,6 +122,9 @@ final class Histogram {
public void addFields(List<Field> fields) {
this.fields.addAll(fields);
for (Field field : fields) {
field.functionFactory = Function.createFactory(field);
}
}
public void add(RecordedEvent e, FilteredType type, List<Field> sourceFields) {
@ -168,7 +171,7 @@ final class Histogram {
private Function[] createFunctions() {
Function[] functions = new Function[fields.size()];
for (int i = 0; i < functions.length; i++) {
functions[i] = Function.create(fields.get(i));
functions[i] = fields.get(i).functionFactory.newFunction();
}
return functions;
}