add unit type for bytes

This commit is contained in:
2023-03-17 16:53:34 +01:00
parent 686e3edd60
commit 359c17bf29
6 changed files with 150 additions and 31 deletions

View File

@@ -7,6 +7,8 @@ public enum RangeUnit {
NO_UNIT(false, Type.Number, "Value"),
AUTOMATIC_BYTES(true, Type.Number, "Value"),
BYTES(false, Type.Number, "Value"),
AUTOMATIC_TIME(true, Type.Duration, "Duration"),
@@ -43,6 +45,10 @@ public enum RangeUnit {
return type == Type.Number || type == Type.HistogramCount;
}
public boolean isBytes() {
return this == BYTES || this == AUTOMATIC_BYTES;
}
public String getLabel() {
return axisLabel;
}
@@ -51,11 +57,9 @@ public enum RangeUnit {
return type;
}
public int valueForUnit(final int value) {
public long valueForUnit(final long value) {
switch (this) {
case AUTOMATIC_NUMBER:
return Integer.MAX_VALUE;
case NO_UNIT:
case BYTES:
return value;
@@ -69,10 +73,12 @@ public enum RangeUnit {
return value * 60 * 60 * 1000;
case DAYS:
return value * 24 * 60 * 60 * 1000;
case AUTOMATIC_NUMBER:
case AUTOMATIC_TIME:
return Integer.MAX_VALUE;
case AUTOMATIC_BYTES:
return Long.MAX_VALUE;
}
return Integer.MAX_VALUE;
return Long.MAX_VALUE;
}
}

View File

@@ -3,8 +3,8 @@ package org.lucares.pdb.plot.api;
public class YAxisDefinition {
private AxisScale axisScale = AxisScale.LINEAR;
private int rangeMin = 0;
private int rangeMax = 300;
private long rangeMin = 0;
private long rangeMax = 300;
private RangeUnit rangeUnit = RangeUnit.AUTOMATIC_TIME;
public AxisScale getAxisScale() {
@@ -23,7 +23,7 @@ public class YAxisDefinition {
return rangeUnit.valueForUnit(rangeMax);
}
public int getRangeMin() {
public long getRangeMin() {
return rangeMin;
}
@@ -31,15 +31,15 @@ public class YAxisDefinition {
return !rangeUnit.isAutomatic() && rangeMin >= 0 && rangeMax >= 0 && rangeMin < rangeMax;
}
public void setRangeMin(final int rangeMin) {
public void setRangeMin(final long rangeMin) {
this.rangeMin = rangeMin;
}
public int getRangeMax() {
public long getRangeMax() {
return rangeMax;
}
public void setRangeMax(final int rangeMax) {
public void setRangeMax(final long rangeMax) {
this.rangeMax = rangeMax;
}

View File

@@ -13,6 +13,7 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.lucares.pdb.plot.api.YAxisDefinition;
import org.lucares.utils.HumanBytes;
class YAxisTicks {
@@ -45,6 +46,17 @@ class YAxisTicks {
default:
throw new IllegalStateException("unhandled value: " + yAxisDefinition.getRangeUnit());
}
} else if (yAxisDefinition.getRangeUnit().isBytes()) {
switch (yAxisDefinition.getAxisScale()) {
case LINEAR:
result = computeLinearYTicksByte(height, yRangeMin, yRangeMax);
break;
case LOG10:
result = computeLog10YTicksByte(height, yRangeMin, yRangeMax);
break;
default:
throw new IllegalArgumentException("Unexpected value: " + yAxisDefinition.getAxisScale());
}
} else {
switch (yAxisDefinition.getAxisScale()) {
case LINEAR:
@@ -59,6 +71,33 @@ class YAxisTicks {
return result;
}
private static double log2(final double d) {
return Math.log10(d) / Math.log10(2);
}
private static List<String> computeLog10YTicksByte(final int height, final long yRangeMin, final long yRangeMax) {
final int fontHeight = GnuplotSettings.TICKS_FONT_SIZE * 2;
final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
final int heightPerPowerOf2 = (int) Math.ceil(plotHeight / log2(yRangeMax));
final List<String> ticsLabels = new ArrayList<>();
long nextFreePositionOnYAxis = 0;
int count = 1;
for (long v = 1; v <= yRangeMax * 10; v *= 2) // increase yRangeMax by factor 10, because Gnuplot uses the next
// log10 value when scaling the y-axis
{
if (nextFreePositionOnYAxis < count * heightPerPowerOf2) {
ticsLabels.add("\"" + HumanBytes.toHumanBytes(v) + "\" " + v);
nextFreePositionOnYAxis = count * heightPerPowerOf2 + fontHeight;
}
count++;
}
return ticsLabels;
}
private static List<String> computeLog10YTicksTime(final int height, final long yRangeMin, final long yRangeMax) {
final List<String> ticsLabels = Arrays.asList(//
@@ -100,6 +139,52 @@ class YAxisTicks {
return ticsLabels;
}
private static List<String> computeLinearYTicksByte(final long height, final long yRangeMinInMs,
final long yRangeMaxInMs) {
final long plotHeight = height - GnuplotSettings.GNUPLOT_TOP_BOTTOM_MARGIN;
final long maxLabels = plotHeight / (GnuplotSettings.TICKS_FONT_SIZE * 2);
final long range = yRangeMaxInMs - yRangeMinInMs;
final long rangePerLabel = roundToNextLinearByteStep(range / maxLabels);
final List<String> ticsLabels = new ArrayList<>();
for (long i = yRangeMinInMs; i <= yRangeMaxInMs; i += rangePerLabel) {
ticsLabels.add("\"" + byteToTic(i, rangePerLabel) + "\" " + i);
}
return ticsLabels;
}
private static long roundToNextLinearByteStep(final long stepSize) {
final List<Long> steps = Arrays.asList(1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L, 256L, 512L,
HumanBytes.KB, HumanBytes.KB * 5, HumanBytes.KB * 10, HumanBytes.KB * 50, HumanBytes.KB * 100,
HumanBytes.KB * 128, HumanBytes.KB * 256, HumanBytes.KB * 512,
HumanBytes.MB, HumanBytes.MB * 5, HumanBytes.MB * 10, HumanBytes.MB * 50, HumanBytes.MB * 100,
HumanBytes.MB * 128, HumanBytes.MB * 256, HumanBytes.MB * 512,
HumanBytes.GB, HumanBytes.GB * 5, HumanBytes.GB * 10, HumanBytes.GB * 50, HumanBytes.GB * 100,
HumanBytes.GB * 128, HumanBytes.GB * 256, HumanBytes.GB * 512,
HumanBytes.TB, HumanBytes.TB * 5, HumanBytes.TB * 10, HumanBytes.TB * 50, HumanBytes.TB * 100,
HumanBytes.TB * 128, HumanBytes.TB * 256, HumanBytes.TB * 512,
HumanBytes.PB, HumanBytes.PB * 5, HumanBytes.PB * 10, HumanBytes.PB * 50, HumanBytes.PB * 100,
HumanBytes.PB * 128, HumanBytes.PB * 256, HumanBytes.PB * 512,
HumanBytes.EB, HumanBytes.EB * 5, HumanBytes.EB * 10, HumanBytes.EB * 50, HumanBytes.EB * 100,
HumanBytes.EB * 128, HumanBytes.EB * 256, HumanBytes.EB * 512);
for (final Long step : steps) {
if (stepSize < step) {
return step;
}
}
return stepSize;
}
private static List<String> computeLinearYTicksTime(final long height, final long yRangeMinInMs,
final long yRangeMaxInMs) {
@@ -156,6 +241,10 @@ class YAxisTicks {
return msPerLabel;
}
private static String byteToTic(final long val, final double rangePerLabel) {
return HumanBytes.toHumanBytes(val);
}
private static String msToTic(final long ms, final double msPerLabel) {
if (ms < 1000) {