159 lines
6.1 KiB
Java
159 lines
6.1 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 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
|
|
*/
|
|
class Utils {
|
|
private 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());
|
|
}
|
|
|
|
|
|
private 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);
|
|
}
|
|
|
|
private 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;
|
|
}
|
|
|
|
private static List<CompressorResult> executeAll(byte[] input, List<AbstractAlgorithm> compressors) {
|
|
return compressors.stream().map(c -> executeCompressor(input, c)).collect(Collectors.toList());
|
|
}
|
|
|
|
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("|--------------------------------------------------------------------------|");
|
|
}
|
|
|
|
private 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;
|
|
|
|
CompressorResult(AbstractAlgorithm compressor, boolean decompressFailed, int size, float difference, int timeInNS, int decompressTimeInNS) {
|
|
this.compressor = compressor;
|
|
this.decompressFailed = decompressFailed;
|
|
this.size = size;
|
|
this.difference = difference;
|
|
this.timeInNS = timeInNS;
|
|
this.decompressTimeInNS = decompressTimeInNS;
|
|
}
|
|
|
|
AbstractAlgorithm getCompressor() {
|
|
return compressor;
|
|
}
|
|
|
|
boolean isDecompressFailed() {
|
|
return decompressFailed;
|
|
}
|
|
|
|
int getSize() {
|
|
return size;
|
|
}
|
|
|
|
float getDifference() {
|
|
return difference;
|
|
}
|
|
|
|
int getTimeInNS() {
|
|
return timeInNS;
|
|
}
|
|
|
|
int getDecompressTimeInNS() {
|
|
return decompressTimeInNS;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(@NotNull Utils.CompressorResult o) {
|
|
return Integer.compare(size, o.getSize());
|
|
}
|
|
}
|
|
|
|
static class DummyCompressor extends AbstractAlgorithm {
|
|
@Override public String getName() { return "Orginaal"; }
|
|
|
|
static CompressorResult of(int size){
|
|
return new CompressorResult(new DummyCompressor(), false, size, 1.0F, -1, -1);
|
|
}
|
|
}
|
|
}
|