java-class-compression-rese.../src/main/java/eu/mikroskeem/uurimustoo/algoritmidetest/Utils.java

130 lines
5.3 KiB
Java

package eu.mikroskeem.uurimustoo.algoritmidetest;
import eu.mikroskeem.shuriken.instrumentation.validate.Validate;
import eu.mikroskeem.shuriken.reflect.Reflect;
import eu.mikroskeem.uurimustoo.algoritmidetest.algoritmid.AbstractAlgorithm;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static eu.mikroskeem.uurimustoo.algoritmidetest.Utils.DummyCompressor.of;
/**
* @author Mark Vainomaa
*/
public class Utils {
public static List<AbstractAlgorithm> getAllCompressors() {
return new FastClasspathScanner(AbstractAlgorithm.class.getPackage().getName())
.scan().getNamesOfSubclassesOf(AbstractAlgorithm.class)
.stream()
.map(className -> {
try {
return (AbstractAlgorithm) Reflect.getClass(className).get().construct().getClassInstance();
} catch (Exception e){
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
public static CompressorResult executeCompressor(byte[] input, AbstractAlgorithm compressor) {
String compressorName = compressor.getName();
boolean decompressFailed = false;
/* Measure compressing speed */
Instant start = Instant.now();
byte[] compressed = compressor.compress(input);
Instant end = Instant.now();
/* Measure decompressing speed and validate it */
Instant start2 = null;
Instant end2 = null;
try {
start2 = Instant.now();
byte[] decompressed = compressor.decompress(compressed);
end2 = Instant.now();
Validate.checkGeneratedClass(decompressed);
assert decompressed.length == input.length;
} catch (Throwable e) {
System.out.println(String.format("Tekkis viga %s algoritmi lahtipakkimisel! %s", compressorName, e.toString()));
decompressFailed = true;
}
float sizeDiff = (float)input.length / (float)compressed.length;
int compressTime = Duration.between(start, end).getNano();
int decompressTime = (start2 != null && end2 != null) ? Duration.between(start2, end2).getNano() : -1;
return new CompressorResult(compressor, decompressFailed, compressed.length, sizeDiff, compressTime, decompressTime);
}
public static List<CompressorResult> executeAllNTimes(byte[] input, int n) {
int i = 0;
List<CompressorResult> lastExecuted = executeAll(input, getAllCompressors());
while(i < n-1){
lastExecuted = executeAll(input, lastExecuted.stream()
.filter(r -> !r.isDecompressFailed())
.map(CompressorResult::getCompressor)
.collect(Collectors.toList()));
i++;
}
lastExecuted.add(of(input.length));
Collections.sort(lastExecuted);
Collections.reverse(lastExecuted);
return lastExecuted;
}
public static List<CompressorResult> executeAll(byte[] input, List<AbstractAlgorithm> compressors) {
return compressors.stream().map(c -> executeCompressor(input, c)).collect(Collectors.toList());
}
public static void generateReport(byte[] input) {
System.out.println("----------------------------------------------------------------------------");
System.out.println("| Algoritm | Suurus | Väiksem | Aeg (kokku) | Aeg (lahti) |");
/* Show other results */
executeAllNTimes(input, 100).forEach(compressorResult -> {
System.out.println("|----------------|--------------|--------------|-------------|-------------|");
System.out.format("| %-12s| %-10s| x%-10.3f| %-9s| %-9s|%n",
compressorResult.getCompressor().getName(),
compressorResult.getSize(),
compressorResult.getDifference(),
(compressorResult.getTimeInNS() / 1000000) + "ms",
(compressorResult.getDecompressTimeInNS() / 1000000) + "ms"
);
});
System.out.println("|--------------------------------------------------------------------------|");
}
@RequiredArgsConstructor
@Getter
public static class CompressorResult implements Comparable<CompressorResult> {
private final AbstractAlgorithm compressor;
private final boolean decompressFailed;
private final int size;
private final float difference;
private final int timeInNS;
private final int decompressTimeInNS;
@Override
public int compareTo(@NotNull Utils.CompressorResult o) {
return Integer.compare(size, o.getSize());
}
}
static class DummyCompressor extends AbstractAlgorithm {
@Getter private final String name = "Orginaal";
static CompressorResult of(int size){
return new CompressorResult(new DummyCompressor(), false, size, 1.0F, -1, -1);
}
}
}