Skip to content

Commit

Permalink
resolve performance issue caused by using DoubleArrayCache.getArrayExact
Browse files Browse the repository at this point in the history
displaying live data from data sets with fluctuating size created a lot of GC pressure because the DoubleArrayCache required a new allocation almost every call to getArrayExact
adjusting the ErrorDataSetRenderer and related classes to call DoubleArrayCache.getArray (using best fit strategy) instead removes this overhead
the time spend in the cache easily took 90% of the render time in our case, because the cache list grews quite large
  • Loading branch information
protogenes committed Nov 6, 2022
1 parent 5719d92 commit 72082bc
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,28 @@ public final IntegerProperty minPointPixelDistanceProperty() {
public int reducePoints(final double[] xValues, final double[] yValues, final double[] xPointErrorsPos,
final double[] xPointErrorsNeg, final double[] yPointErrorsPos, final double[] yPointErrorsNeg,
final String[] styles, final boolean[] pointSelected, final int indexMin, final int indexMax) {
AssertUtils.nonEmptyArray("xValues", xValues);
final int defaultDataLength = xValues.length;
AssertUtils.checkArrayDimension("yValues", yValues, defaultDataLength);
AssertUtils.checkArrayDimension("pointSelected", pointSelected, defaultDataLength);
AssertUtils.gtEqThanZero("indexMax", indexMin);
AssertUtils.gtEqThanZero("indexMin", indexMin);
AssertUtils.gtThanZero("indexMax", indexMax);
AssertUtils.indexOrder(indexMin,"indexMin", indexMax,"indexMax");
AssertUtils.checkArrayCapacity("xValues", xValues, indexMax + 1);
AssertUtils.checkArrayCapacity("yValues", yValues, indexMax + 1);
AssertUtils.checkArrayCapacity("pointSelected", pointSelected, indexMax + 1);

final boolean xErrorPos = xPointErrorsPos != null;
final boolean xErrorNeg = xPointErrorsNeg != null;
final boolean yErrorPos = yPointErrorsPos != null;
final boolean yErrorNeg = yPointErrorsNeg != null;

if (xErrorPos && xErrorNeg && yErrorPos && yErrorNeg) {
AssertUtils.checkArrayDimension("xPointErrorsPos", xPointErrorsPos, defaultDataLength);
AssertUtils.checkArrayDimension("xPointErrorsNeg", xPointErrorsNeg, defaultDataLength);
AssertUtils.checkArrayDimension("yPointErrorsPos", yPointErrorsPos, defaultDataLength);
AssertUtils.checkArrayDimension("yPointErrorsNeg", yPointErrorsNeg, defaultDataLength);
AssertUtils.checkArrayCapacity("xPointErrorsPos", xPointErrorsPos, indexMax + 1);
AssertUtils.checkArrayCapacity("xPointErrorsNeg", xPointErrorsNeg, indexMax + 1);
AssertUtils.checkArrayCapacity("yPointErrorsPos", yPointErrorsPos, indexMax + 1);
AssertUtils.checkArrayCapacity("yPointErrorsNeg", yPointErrorsNeg, indexMax + 1);
return reducePointsInternal(xValues, yValues, xPointErrorsPos, xPointErrorsNeg, yPointErrorsPos,
yPointErrorsNeg, styles, pointSelected, indexMin, indexMax);
} else if (yErrorPos && yErrorNeg) {
AssertUtils.checkArrayDimension("yPointErrorsPos", yPointErrorsPos, defaultDataLength);
AssertUtils.checkArrayDimension("yPointErrorsNeg", yPointErrorsNeg, defaultDataLength);
AssertUtils.checkArrayCapacity("yPointErrorsPos", yPointErrorsPos, indexMax + 1);
AssertUtils.checkArrayCapacity("yPointErrorsNeg", yPointErrorsNeg, indexMax + 1);
return reducePointsInternal(xValues, yValues, yPointErrorsPos, yPointErrorsNeg, styles, pointSelected,
indexMin, indexMax);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ class CachedDataPoints {

public CachedDataPoints(final int indexMin, final int indexMax, final int dataLength, final boolean full) {
maxDataCount = dataLength;
xValues = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
yValues = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
xValues = DoubleArrayCache.getInstance().getArray(maxDataCount);
yValues = DoubleArrayCache.getInstance().getArray(maxDataCount);
styles = ArrayCache.getCachedStringArray(STYLES2, dataLength);
this.indexMin = indexMin;
this.indexMax = indexMax;
errorYNeg = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
errorYPos = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
errorYNeg = DoubleArrayCache.getInstance().getArray(maxDataCount);
errorYPos = DoubleArrayCache.getInstance().getArray(maxDataCount);
if (full) {
errorXNeg = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
errorXPos = DoubleArrayCache.getInstance().getArrayExact(maxDataCount);
errorXNeg = DoubleArrayCache.getInstance().getArray(maxDataCount);
errorXPos = DoubleArrayCache.getInstance().getArray(maxDataCount);
}
selected = ArrayCache.getCachedBooleanArray(SELECTED2, dataLength);
ArrayUtils.fillArray(styles, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,8 +479,8 @@ protected void drawErrorSurface(final GraphicsContext gc, final CachedDataPoints

final int nDataCount = localCachedPoints.actualDataCount;
final int nPolygoneEdges = 2 * nDataCount;
final double[] xValuesSurface = DoubleArrayCache.getInstance().getArrayExact(nPolygoneEdges);
final double[] yValuesSurface = DoubleArrayCache.getInstance().getArrayExact(nPolygoneEdges);
final double[] xValuesSurface = DoubleArrayCache.getInstance().getArray(nPolygoneEdges);
final double[] yValuesSurface = DoubleArrayCache.getInstance().getArray(nPolygoneEdges);

final int xend = nPolygoneEdges - 1;
for (int i = 0; i < nDataCount; i++) {
Expand Down Expand Up @@ -520,8 +520,8 @@ protected void drawErrorSurfaceNaNCompatible(final GraphicsContext gc, final Cac

final int nDataCount = localCachedPoints.actualDataCount;
final int nPolygoneEdges = 2 * nDataCount;
final double[] xValuesSurface = DoubleArrayCache.getInstance().getArrayExact(nPolygoneEdges);
final double[] yValuesSurface = DoubleArrayCache.getInstance().getArrayExact(nPolygoneEdges);
final double[] xValuesSurface = DoubleArrayCache.getInstance().getArray(nPolygoneEdges);
final double[] yValuesSurface = DoubleArrayCache.getInstance().getArray(nPolygoneEdges);

final int xend = nPolygoneEdges - 1;
int count = 0;
Expand Down Expand Up @@ -733,8 +733,8 @@ protected static void drawPolyLineArea(final GraphicsContext gc, final CachedDat
}

// need to allocate new array :-(
final double[] newX = DoubleArrayCache.getInstance().getArrayExact(n + 2);
final double[] newY = DoubleArrayCache.getInstance().getArrayExact(n + 2);
final double[] newX = DoubleArrayCache.getInstance().getArray(n + 2);
final double[] newY = DoubleArrayCache.getInstance().getArray(n + 2);

final double zero = localCachedPoints.yZero;
System.arraycopy(localCachedPoints.xValues, 0, newX, 0, n);
Expand Down Expand Up @@ -765,8 +765,8 @@ protected static void drawPolyLineHistogram(final GraphicsContext gc, final Cach
}

// need to allocate new array :-(
final double[] newX = DoubleArrayCache.getInstance().getArrayExact(2 * (n + 1));
final double[] newY = DoubleArrayCache.getInstance().getArrayExact(2 * (n + 1));
final double[] newX = DoubleArrayCache.getInstance().getArray(2 * (n + 1));
final double[] newY = DoubleArrayCache.getInstance().getArray(2 * (n + 1));

final double xRange = localCachedPoints.xMax - localCachedPoints.xMin;
double diffLeft;
Expand Down Expand Up @@ -818,10 +818,10 @@ protected static void drawPolyLineHistogramBezier(final GraphicsContext gc,
}

// need to allocate new array :-(
final double[] xCp1 = DoubleArrayCache.getInstance().getArrayExact(n);
final double[] yCp1 = DoubleArrayCache.getInstance().getArrayExact(n);
final double[] xCp2 = DoubleArrayCache.getInstance().getArrayExact(n);
final double[] yCp2 = DoubleArrayCache.getInstance().getArrayExact(n);
final double[] xCp1 = DoubleArrayCache.getInstance().getArray(n);
final double[] yCp1 = DoubleArrayCache.getInstance().getArray(n);
final double[] xCp2 = DoubleArrayCache.getInstance().getArray(n);
final double[] yCp2 = DoubleArrayCache.getInstance().getArray(n);

BezierCurve.calcCurveControlPoints(localCachedPoints.xValues, localCachedPoints.yValues, xCp1, yCp1, xCp2, yCp2,
localCachedPoints.actualDataCount);
Expand Down Expand Up @@ -869,8 +869,8 @@ protected static void drawPolyLineHistogramFilled(final GraphicsContext gc,
}

// need to allocate new array :-(
final double[] newX = DoubleArrayCache.getInstance().getArrayExact(2 * (n + 1));
final double[] newY = DoubleArrayCache.getInstance().getArrayExact(2 * (n + 1));
final double[] newX = DoubleArrayCache.getInstance().getArray(2 * (n + 1));
final double[] newY = DoubleArrayCache.getInstance().getArray(2 * (n + 1));

final double xRange = localCachedPoints.xMax - localCachedPoints.xMin;
double diffLeft;
Expand Down Expand Up @@ -963,8 +963,8 @@ protected static void drawPolyLineStairCase(final GraphicsContext gc, final Cach
}

// need to allocate new array :-(
final double[] newX = DoubleArrayCache.getInstance().getArrayExact(2 * n);
final double[] newY = DoubleArrayCache.getInstance().getArrayExact(2 * n);
final double[] newX = DoubleArrayCache.getInstance().getArray(2 * n);
final double[] newY = DoubleArrayCache.getInstance().getArray(2 * n);

for (int i = 0; i < n - 1; i++) {
newX[2 * i] = localCachedPoints.xValues[i];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,46 @@ public static void checkArrayDimension(final String name, final int[] array, fin
}
}

public static void checkArrayCapacity(final String name, final boolean[] array, final int requiredLength) {
AssertUtils.notNull(name, array);
AssertUtils.nonEmptyArray(name, array);
if (array.length < requiredLength) {
throw new IllegalArgumentException("The " + name + " boolean array must have a length of at least " + requiredLength);
}
}

public static void checkArrayCapacity(final String name, final byte[] array, final int requiredLength) {
AssertUtils.notNull(name, array);
AssertUtils.nonEmptyArray(name, array);
if (array.length < requiredLength) {
throw new IllegalArgumentException("The " + name + " byte array must have a length of at least " + requiredLength);
}
}

public static void checkArrayCapacity(final String name, final double[] array, final int requiredLength) {
AssertUtils.notNull(name, array);
AssertUtils.nonEmptyArray(name, array);
if (array.length < requiredLength) {
throw new IllegalArgumentException("The " + name + " double array must have a length of at least " + requiredLength);
}
}

public static void checkArrayCapacity(final String name, final float[] array, final int requiredLength) {
AssertUtils.notNull(name, array);
AssertUtils.nonEmptyArray(name, array);
if (array.length < requiredLength) {
throw new IllegalArgumentException("The " + name + " float array must have a length of at least " + requiredLength);
}
}

public static void checkArrayCapacity(final String name, final int[] array, final int requiredLength) {
AssertUtils.notNull(name, array);
AssertUtils.nonEmptyArray(name, array);
if (array.length < requiredLength) {
throw new IllegalArgumentException("The " + name + " int array must have a length of at least " + requiredLength);
}
}

/**
* Asserts that the specified arrays have the same length.
*
Expand Down

0 comments on commit 72082bc

Please sign in to comment.