add unit type for bytes
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package org.lucares.pdb.map;
|
package org.lucares.pdb.map;
|
||||||
|
|
||||||
import java.util.List;
|
import org.lucares.utils.HumanBytes;
|
||||||
|
|
||||||
public class PersistentMapStats {
|
public class PersistentMapStats {
|
||||||
private long values = 0;
|
private long values = 0;
|
||||||
@@ -87,7 +87,7 @@ public class PersistentMapStats {
|
|||||||
builder.append(String.format("\navg. depth= %.2f", averageDepth));
|
builder.append(String.format("\navg. depth= %.2f", averageDepth));
|
||||||
builder.append(String.format("\navg. fill= %.2f", averageFill));
|
builder.append(String.format("\navg. fill= %.2f", averageFill));
|
||||||
builder.append(String.format("\nvalues/node=%.2f", averageValuesInNode));
|
builder.append(String.format("\nvalues/node=%.2f", averageValuesInNode));
|
||||||
builder.append(String.format("\nfile size= %s\n", toHumanBytes(fileSize)));
|
builder.append(String.format("\nfile size= %s\n", HumanBytes.toHumanBytes(fileSize)));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,21 +100,9 @@ public class PersistentMapStats {
|
|||||||
builder.append(String.format("\navg. depth= %.2f -> %.2f", old.averageDepth, averageDepth));
|
builder.append(String.format("\navg. depth= %.2f -> %.2f", old.averageDepth, averageDepth));
|
||||||
builder.append(String.format("\navg. fill= %.2f -> %.2f", old.averageFill, averageFill));
|
builder.append(String.format("\navg. fill= %.2f -> %.2f", old.averageFill, averageFill));
|
||||||
builder.append(String.format("\nvalues/node=%.2f -> %.2f", old.averageValuesInNode, averageValuesInNode));
|
builder.append(String.format("\nvalues/node=%.2f -> %.2f", old.averageValuesInNode, averageValuesInNode));
|
||||||
builder.append(String.format("\nfile size= %s -> %s\n", toHumanBytes(old.fileSize), toHumanBytes(fileSize)));
|
builder.append(String.format("\nfile size= %s -> %s\n", HumanBytes.toHumanBytes(old.fileSize),
|
||||||
|
HumanBytes.toHumanBytes(fileSize)));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toHumanBytes(final long bytes) {
|
|
||||||
final List<String> powers = List.of("bytes", "KB", "MB", "GB", "TB", "PB", "EB");
|
|
||||||
|
|
||||||
int power = 1;
|
|
||||||
String result = String.format("%d bytes", bytes);
|
|
||||||
while (bytes >= Math.pow(1024, power) && power < powers.size()) {
|
|
||||||
result = String.format("%.3f", bytes / Math.pow(1024, power));
|
|
||||||
result = result.replaceAll("\\.?0*$", "");
|
|
||||||
result = result + " " + powers.get(power);
|
|
||||||
power = power + 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,15 @@
|
|||||||
<mat-form-field class="pdb-form-mid">
|
<mat-form-field class="pdb-form-mid">
|
||||||
<mat-label>Y{{yIndex}}-Axis Unit:</mat-label>
|
<mat-label>Y{{yIndex}}-Axis Unit:</mat-label>
|
||||||
<mat-select [(value)]="yAxisUnit">
|
<mat-select [(value)]="yAxisUnit">
|
||||||
<mat-optgroup label="⸺numbers⸺">
|
<mat-optgroup label="—numbers—">
|
||||||
<mat-option value="AUTOMATIC_NUMBER">auto (number)</mat-option>
|
<mat-option value="AUTOMATIC_NUMBER">auto (number)</mat-option>
|
||||||
<mat-option value="NO_UNIT">no unit</mat-option>
|
<mat-option value="NO_UNIT">no unit</mat-option>
|
||||||
</mat-optgroup>
|
</mat-optgroup>
|
||||||
<mat-optgroup label="⸺time⸺">
|
<mat-optgroup label="—bytes—">
|
||||||
|
<mat-option value="AUTOMATIC_BYTES">auto (bytes)</mat-option>
|
||||||
|
<mat-option value="BYTES">bytes</mat-option>
|
||||||
|
</mat-optgroup>
|
||||||
|
<mat-optgroup label="—time—">
|
||||||
<mat-option value="AUTOMATIC_TIME">auto (time)</mat-option>
|
<mat-option value="AUTOMATIC_TIME">auto (time)</mat-option>
|
||||||
<mat-option value="MILLISECONDS">millis</mat-option>
|
<mat-option value="MILLISECONDS">millis</mat-option>
|
||||||
<mat-option value="SECONDS">seconds</mat-option>
|
<mat-option value="SECONDS">seconds</mat-option>
|
||||||
@@ -25,11 +29,11 @@
|
|||||||
</mat-optgroup>
|
</mat-optgroup>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngIf="yAxisUnit !== 'AUTOMATIC_TIME' && yAxisUnit !== 'AUTOMATIC_NUMBER'" class="pdb-form-number">
|
<mat-form-field *ngIf="yAxisUnit !== 'AUTOMATIC_TIME' && yAxisUnit !== 'AUTOMATIC_NUMBER' && yAxisUnit !== 'AUTOMATIC_BYTES'" class="pdb-form-number">
|
||||||
<mat-label>Min:</mat-label>
|
<mat-label>Min:</mat-label>
|
||||||
<input matInput type="number" placeholder="Min" min="0" [(ngModel)]="minYValue">
|
<input matInput type="number" placeholder="Min" min="0" [(ngModel)]="minYValue">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngIf="yAxisUnit !== 'AUTOMATIC_TIME' && yAxisUnit !== 'AUTOMATIC_NUMBER'" class="pdb-form-number">
|
<mat-form-field *ngIf="yAxisUnit !== 'AUTOMATIC_TIME' && yAxisUnit !== 'AUTOMATIC_NUMBER' && yAxisUnit !== 'AUTOMATIC_BYTES'" class="pdb-form-number">
|
||||||
<mat-label>Max:</mat-label>
|
<mat-label>Max:</mat-label>
|
||||||
<input matInput type="number" placeholder="Max" min="0" [(ngModel)]="maxYValue">
|
<input matInput type="number" placeholder="Max" min="0" [(ngModel)]="maxYValue">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ public enum RangeUnit {
|
|||||||
|
|
||||||
NO_UNIT(false, Type.Number, "Value"),
|
NO_UNIT(false, Type.Number, "Value"),
|
||||||
|
|
||||||
|
AUTOMATIC_BYTES(true, Type.Number, "Value"),
|
||||||
|
|
||||||
BYTES(false, Type.Number, "Value"),
|
BYTES(false, Type.Number, "Value"),
|
||||||
|
|
||||||
AUTOMATIC_TIME(true, Type.Duration, "Duration"),
|
AUTOMATIC_TIME(true, Type.Duration, "Duration"),
|
||||||
@@ -43,6 +45,10 @@ public enum RangeUnit {
|
|||||||
return type == Type.Number || type == Type.HistogramCount;
|
return type == Type.Number || type == Type.HistogramCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBytes() {
|
||||||
|
return this == BYTES || this == AUTOMATIC_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return axisLabel;
|
return axisLabel;
|
||||||
}
|
}
|
||||||
@@ -51,11 +57,9 @@ public enum RangeUnit {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int valueForUnit(final int value) {
|
public long valueForUnit(final long value) {
|
||||||
|
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case AUTOMATIC_NUMBER:
|
|
||||||
return Integer.MAX_VALUE;
|
|
||||||
case NO_UNIT:
|
case NO_UNIT:
|
||||||
case BYTES:
|
case BYTES:
|
||||||
return value;
|
return value;
|
||||||
@@ -69,10 +73,12 @@ public enum RangeUnit {
|
|||||||
return value * 60 * 60 * 1000;
|
return value * 60 * 60 * 1000;
|
||||||
case DAYS:
|
case DAYS:
|
||||||
return value * 24 * 60 * 60 * 1000;
|
return value * 24 * 60 * 60 * 1000;
|
||||||
|
case AUTOMATIC_NUMBER:
|
||||||
case AUTOMATIC_TIME:
|
case AUTOMATIC_TIME:
|
||||||
return Integer.MAX_VALUE;
|
case AUTOMATIC_BYTES:
|
||||||
|
return Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
return Integer.MAX_VALUE;
|
return Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package org.lucares.pdb.plot.api;
|
|||||||
public class YAxisDefinition {
|
public class YAxisDefinition {
|
||||||
private AxisScale axisScale = AxisScale.LINEAR;
|
private AxisScale axisScale = AxisScale.LINEAR;
|
||||||
|
|
||||||
private int rangeMin = 0;
|
private long rangeMin = 0;
|
||||||
private int rangeMax = 300;
|
private long rangeMax = 300;
|
||||||
private RangeUnit rangeUnit = RangeUnit.AUTOMATIC_TIME;
|
private RangeUnit rangeUnit = RangeUnit.AUTOMATIC_TIME;
|
||||||
|
|
||||||
public AxisScale getAxisScale() {
|
public AxisScale getAxisScale() {
|
||||||
@@ -23,7 +23,7 @@ public class YAxisDefinition {
|
|||||||
return rangeUnit.valueForUnit(rangeMax);
|
return rangeUnit.valueForUnit(rangeMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRangeMin() {
|
public long getRangeMin() {
|
||||||
return rangeMin;
|
return rangeMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,15 +31,15 @@ public class YAxisDefinition {
|
|||||||
return !rangeUnit.isAutomatic() && rangeMin >= 0 && rangeMax >= 0 && rangeMin < rangeMax;
|
return !rangeUnit.isAutomatic() && rangeMin >= 0 && rangeMax >= 0 && rangeMin < rangeMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRangeMin(final int rangeMin) {
|
public void setRangeMin(final long rangeMin) {
|
||||||
this.rangeMin = rangeMin;
|
this.rangeMin = rangeMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRangeMax() {
|
public long getRangeMax() {
|
||||||
return rangeMax;
|
return rangeMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRangeMax(final int rangeMax) {
|
public void setRangeMax(final long rangeMax) {
|
||||||
this.rangeMax = rangeMax;
|
this.rangeMax = rangeMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.Locale;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.lucares.pdb.plot.api.YAxisDefinition;
|
import org.lucares.pdb.plot.api.YAxisDefinition;
|
||||||
|
import org.lucares.utils.HumanBytes;
|
||||||
|
|
||||||
class YAxisTicks {
|
class YAxisTicks {
|
||||||
|
|
||||||
@@ -45,6 +46,17 @@ class YAxisTicks {
|
|||||||
default:
|
default:
|
||||||
throw new IllegalStateException("unhandled value: " + yAxisDefinition.getRangeUnit());
|
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 {
|
} else {
|
||||||
switch (yAxisDefinition.getAxisScale()) {
|
switch (yAxisDefinition.getAxisScale()) {
|
||||||
case LINEAR:
|
case LINEAR:
|
||||||
@@ -59,6 +71,33 @@ class YAxisTicks {
|
|||||||
return result;
|
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) {
|
private static List<String> computeLog10YTicksTime(final int height, final long yRangeMin, final long yRangeMax) {
|
||||||
|
|
||||||
final List<String> ticsLabels = Arrays.asList(//
|
final List<String> ticsLabels = Arrays.asList(//
|
||||||
@@ -100,6 +139,52 @@ class YAxisTicks {
|
|||||||
return ticsLabels;
|
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,
|
private static List<String> computeLinearYTicksTime(final long height, final long yRangeMinInMs,
|
||||||
final long yRangeMaxInMs) {
|
final long yRangeMaxInMs) {
|
||||||
|
|
||||||
@@ -156,6 +241,10 @@ class YAxisTicks {
|
|||||||
return msPerLabel;
|
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) {
|
private static String msToTic(final long ms, final double msPerLabel) {
|
||||||
|
|
||||||
if (ms < 1000) {
|
if (ms < 1000) {
|
||||||
|
|||||||
32
pdb-utils/src/main/java/org/lucares/utils/HumanBytes.java
Normal file
32
pdb-utils/src/main/java/org/lucares/utils/HumanBytes.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package org.lucares.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HumanBytes {
|
||||||
|
|
||||||
|
public static final long KB = 1024;
|
||||||
|
|
||||||
|
public static final long MB = KB * 1024;
|
||||||
|
|
||||||
|
public static final long GB = MB * 1024;
|
||||||
|
|
||||||
|
public static final long TB = GB * 1024;
|
||||||
|
|
||||||
|
public static final long PB = TB * 1024;
|
||||||
|
|
||||||
|
public static final long EB = TB * 1024;
|
||||||
|
|
||||||
|
public static String toHumanBytes(final long bytes) {
|
||||||
|
final List<String> powers = List.of("bytes", "KB", "MB", "GB", "TB", "PB", "EB");
|
||||||
|
|
||||||
|
int power = 1;
|
||||||
|
String result = String.format("%d bytes", bytes);
|
||||||
|
while (bytes >= Math.pow(1024, power) && power < powers.size()) {
|
||||||
|
result = String.format("%.3f", bytes / Math.pow(1024, power));
|
||||||
|
result = result.replaceAll("\\.?0*$", "");
|
||||||
|
result = result + " " + powers.get(power);
|
||||||
|
power = power + 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user