From aa826bf10f32ee4e424963b2d2bb8f79f0ce4099 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sat, 28 Jan 2023 17:57:59 +0100 Subject: [PATCH] ex11: done through CSV --- DiSLProject2022/.gitignore | 1 + .../src-profiler/ex11/CallInfo.java | 24 ---------- .../src-profiler/ex11/CallInfoCSVWriter.java | 48 +++++++++++++++++++ .../src-profiler/ex11/Profiler.java | 18 ++++++- 4 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 DiSLProject2022/src-profiler/ex11/CallInfoCSVWriter.java diff --git a/DiSLProject2022/.gitignore b/DiSLProject2022/.gitignore index b9abff2..49c90d4 100644 --- a/DiSLProject2022/.gitignore +++ b/DiSLProject2022/.gitignore @@ -2,4 +2,5 @@ bin-profiler build/profiler.jar *.iml .idea/ +*.csv diff --git a/DiSLProject2022/src-profiler/ex11/CallInfo.java b/DiSLProject2022/src-profiler/ex11/CallInfo.java index 07b4870..0af77bc 100644 --- a/DiSLProject2022/src-profiler/ex11/CallInfo.java +++ b/DiSLProject2022/src-profiler/ex11/CallInfo.java @@ -2,25 +2,7 @@ package ex11; import org.objectweb.asm.Opcodes; -import java.util.Objects; - public record CallInfo(int instruction, long index, String caller, String callee, String callTarget) { - private static final String FORMAT = "CallerMethodFQIN %s\nCallerBCI %d\ninvoketype %s\nCalleeMethodFQIN %s\nCallTargetFQIN %s"; - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CallInfo callInfo = (CallInfo) o; - return instruction == callInfo.instruction && index == callInfo.index && caller.equals(callInfo.caller) && - callee.equals(callInfo.callee) && callTarget.equals(callInfo.callTarget); - } - - @Override - public int hashCode() { - return Objects.hash(instruction, index, caller, callee, callTarget); - } - public String invokeType() { return switch (instruction) { case Opcodes.INVOKEDYNAMIC -> "dynamic"; @@ -31,10 +13,4 @@ public record CallInfo(int instruction, long index, String caller, String callee default -> throw new IllegalStateException("Not an INVOKE* bytecode instruction: " + instruction); }; } - - @Override - public String toString() { - return String.format(FORMAT, caller, index, invokeType(), callee, callTarget); - } - } diff --git a/DiSLProject2022/src-profiler/ex11/CallInfoCSVWriter.java b/DiSLProject2022/src-profiler/ex11/CallInfoCSVWriter.java new file mode 100644 index 0000000..9d74024 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex11/CallInfoCSVWriter.java @@ -0,0 +1,48 @@ +package ex11; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class CallInfoCSVWriter { + + private static final String[] headerLines = new String[]{ + "CallerMethodFQIN", + "CallerBCI", + "invoketype", + "CalleeMethodFQIN", + "CallTargetFQIN", + "#invokes" + }; + + private final BufferedWriter outFile; + + public CallInfoCSVWriter(final OutputStream outFile) throws IOException { + this.outFile = new BufferedWriter(new OutputStreamWriter(outFile)); + writeLine(headerLines); + } + + private static String escapeSpecialCharacters(final String data) { + final String escapedData = data.replaceAll("\\R", " "); + if (data.contains(",") || data.contains("\"") || data.contains("'")) { + return "\"%s\"".formatted(data.replace("\"", "\"\"")); + } else { + return escapedData; + } + } + + private void writeLine(final String... data) throws IOException { + final String line = Stream.of(data) + .map(CallInfoCSVWriter::escapeSpecialCharacters) + .collect(Collectors.joining(",")); + outFile.write(line + "\n"); + } + + public void write(final CallInfo ci, long invokes) throws IOException { + writeLine(ci.caller(), Long.toString(ci.index()), ci.invokeType(), ci.callee(), ci.callTarget(), + Long.toString(invokes)); + } +} diff --git a/DiSLProject2022/src-profiler/ex11/Profiler.java b/DiSLProject2022/src-profiler/ex11/Profiler.java index a6fdb53..f0e0db4 100644 --- a/DiSLProject2022/src-profiler/ex11/Profiler.java +++ b/DiSLProject2022/src-profiler/ex11/Profiler.java @@ -1,18 +1,32 @@ package ex11; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.HashMap; import java.util.Map; public final class Profiler { private static final Map count = new HashMap<>(); + private static final Path outFile = Path.of("ex11.csv"); + private static boolean stop = false; static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { stop = true; - for (final var entry : count.entrySet()) { - System.out.println(entry.getKey().toString() + "\n#invokes " + entry.getValue()[0] + "\n"); + try (final OutputStream path = Files.newOutputStream(outFile, StandardOpenOption.WRITE)) { + final CallInfoCSVWriter w = new CallInfoCSVWriter(path); + for (final var entry : count.entrySet()) { + System.out.println(entry.getKey().toString() + "\n#invokes " + entry.getValue()[0] + "\n"); + w.write(entry.getKey(), entry.getValue()[0]); + } + System.out.println("Invocations have been written to: " + outFile.toAbsolutePath()); + } catch (final IOException e) { + throw new RuntimeException("Writing CSV file with call info failed", e); } })); }