diff --git a/src/main/java/com/performizeit/mjprof/parser/JStackTextualFormatParser.java b/src/main/java/com/performizeit/mjprof/parser/JStackTextualFormatParser.java new file mode 100644 index 0000000..ffa2bd8 --- /dev/null +++ b/src/main/java/com/performizeit/mjprof/parser/JStackTextualFormatParser.java @@ -0,0 +1,164 @@ +package com.performizeit.mjprof.parser; + +import com.performizeit.mjprof.model.Profile; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.performizeit.mjprof.parser.ThreadInfoProps.*; + + +public class JStackTextualFormatParser { + public static final String LOCKED_OWNABLE_SYNCHRONIZERS="Locked ownable synchronizers"; + public static final String JAVA_LANG_THREAD_STATE="java.lang.Thread.State"; + + private void parseThreadHeaderLine(HashMap props, String metaLine) { + Pattern p = Pattern.compile("^\"(.*)\".*"); + Matcher m = p.matcher(metaLine); + + if (m.find()) { + props.put(NAME, m.group(1)); + } + + extractStatus(props,metaLine); + metadataKeyValProperties(props,metaLine); + + if (metaLine.contains("\" " + DAEMON + " ")) { + props.put(DAEMON, true); + } + } + protected void metadataKeyValProperties(HashMap props, String metaLine) { + Pattern p = Pattern.compile("(\\S+)=(\\S+)"); // a non space string then = and then a non space string + Matcher m = p.matcher(metaLine); + while (m.find()) { + props.put(m.group(1), m.group(2)); + } + if (props.get(TID) != null && !props.get(TID).equals("*")) { + props.put(TID + "Long", new HexaLong((String) props.get(TID))); + } + if (props.get(NID) != null && !props.get(NID).equals("*")) { + props.put(NID + "Long", new HexaLong((String) props.get(NID))); + } + } + + + private void parseThreadState(HashMap props,String threadState) { + Pattern p = Pattern.compile("^[\\s]*" + JAVA_LANG_THREAD_STATE + ": (.*)$"); + Matcher m = p.matcher(threadState); + if (m.find()) { + props.put(STATE, m.group(1)); + } + } + + public HashMap parseLegacyTextualFormat(String stackTrace) { + HashMap props = new HashMap<>(); + BufferedReader reader = new BufferedReader(new StringReader(stackTrace)); + try { + String metaLine = reader.readLine(); + if (metaLine != null) { + parseThreadHeaderLine(props, metaLine); + + String threadState = reader.readLine(); + if (threadState != null) { + parseThreadState(props, threadState); + } + String linesOfStack = readUntilEmptyLine(reader); + String s; + props.put(STACK, new Profile(linesOfStack)); + while ((s = reader.readLine()) != null) { + if (s.contains(LOCKED_OWNABLE_SYNCHRONIZERS)) { + String linesOfLOS = readUntilEmptyLine(reader); + if (linesOfLOS.trim().length() > 0) + props.put(LOS, new ThreadLockedOwnableSynchronizers(linesOfLOS)); + } + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return props; + } + + private String readUntilEmptyLine(BufferedReader reader) throws IOException { + StringBuilder chunk = new StringBuilder(); + String s; + while ((s = reader.readLine()) != null) { + if (s.trim().length() == 0) break; + chunk.append(s).append("\n"); + } + return chunk.toString(); + } + + private void extractStatus(HashMap props, String metaLine) { + int idx = metaLine.lastIndexOf('='); + if (idx != -1) { + String lastParam = metaLine.substring(idx); + idx = lastParam.indexOf(' '); + if (idx != -1) { + + lastParam = lastParam.substring(idx + 1); + + if (lastParam.length() > 0) { + props.put(STATUS, lastParam.trim()); + } + } + } + } + + + public String toJStackFormat(HashMap props) { + StringBuilder mdStr = new StringBuilder(); + + if (props.get(NAME) != null) { + mdStr.append("\"").append(props.get(NAME)).append("\""); + } + if (props.get(COUNT) != null) { + mdStr.append(" " + COUNT + "=").append(props.get(COUNT)); + } + if (props.get(DAEMON) != null) { + mdStr.append(" " + DAEMON); + } + if (props.get(PRIO) != null) { + mdStr.append(" " + PRIO + "=").append(props.get(PRIO)); + } + if (props.get(TID) != null) { + mdStr.append(" " + TID + "=").append(props.get(TID)); + } + if (props.get(NID) != null) { + mdStr.append(" " + NID + "=").append(props.get(NID)); + } + if (props.get(STATUS) != null) { + mdStr.append(" ").append(props.get(STATUS)); + } + if (props.get(CPUNS) != null) { + mdStr.append(" " + CPUNS + "=").append(props.get(CPUNS)); + } + if (props.get(WALL) != null) { + mdStr.append(" " + WALL + "=").append(props.get(WALL)); + } + if (props.get(CPU_PREC) != null) { + mdStr.append(" " + CPU_PREC + "=").append(props.get(CPU_PREC)); + } + + + if (props.get(STATE) != null) { + mdStr.append("\n " + JAVA_LANG_THREAD_STATE + ": ").append(props.get(STATE)); + } + + if (props.get(STACK) != null) { + mdStr.append("\n").append(props.get(STACK).toString()); + } + mdStr.append("\n"); + if (props.get(LOS) != null) { + mdStr.append("\n " + LOCKED_OWNABLE_SYNCHRONIZERS + ":\n").append( + props.get(LOS).toString()); + } + + return mdStr.toString(); + } + +} diff --git a/src/main/java/com/performizeit/mjprof/parser/Props.java b/src/main/java/com/performizeit/mjprof/parser/Props.java deleted file mode 100644 index 544b78d..0000000 --- a/src/main/java/com/performizeit/mjprof/parser/Props.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - This file is part of mjprof. - - mjprof is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - mjprof is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with mjprof. If not, see . -*/ - -package com.performizeit.mjprof.parser; - -import java.util.HashMap; -import java.util.Set; - - -public class Props { - HashMap props; - - public Props(HashMap mtd) { - props = mtd; - } - - public Props() { - props = new HashMap<>(); - } - - public HashMap cloneMetaData() { - return (HashMap) props.clone(); - } - - public Object getVal(String key) { - return props.get(key); - } - - public Object setVal(String key, Object val) { - return props.put(key, val); - } - - public Set getProps() { - return props.keySet(); - } -} diff --git a/src/main/java/com/performizeit/mjprof/parser/ThreadInfo.java b/src/main/java/com/performizeit/mjprof/parser/ThreadInfo.java index 0f27bff..d74e189 100644 --- a/src/main/java/com/performizeit/mjprof/parser/ThreadInfo.java +++ b/src/main/java/com/performizeit/mjprof/parser/ThreadInfo.java @@ -17,68 +17,42 @@ package com.performizeit.mjprof.parser; -import com.performizeit.mjprof.model.Profile; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; import java.util.HashMap; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.performizeit.mjprof.parser.ThreadInfoProps.*; +public class ThreadInfo { + HashMap props; + public ThreadInfo(HashMap mtd) { + props = mtd; + } -public class ThreadInfo extends Props { + public ThreadInfo() { + props = new HashMap<>(); + } - public static final String LOCKED_OWNABLE_SYNCHRONIZERS = "Locked ownable synchronizers"; - public static final String JAVA_LANG_THREAD_STATE = "java.lang.Thread.State"; + public HashMap cloneMetaData() { + return (HashMap) props.clone(); + } - public ThreadInfo(String stackTrace) { - BufferedReader reader = new BufferedReader(new StringReader(stackTrace)); - try { - String metaLine = reader.readLine(); - if (metaLine != null) { - parseMetaLine(metaLine); - - String threadState = reader.readLine(); - if (threadState != null) { - parseThreadState(threadState); - } - String linesOfStack = ""; - String s; - while ((s = reader.readLine()) != null) { - if (s.trim().length() == 0) break; - linesOfStack += s + "\n"; - } - props.put(STACK, new Profile(linesOfStack)); - while ((s = reader.readLine()) != null) { - if (s.contains(LOCKED_OWNABLE_SYNCHRONIZERS)) break; - } - String linesOfLOS = ""; - while ((s = reader.readLine()) != null) { - if (s.trim().length() == 0) break; - linesOfLOS += s + "\n"; - } - if (linesOfLOS.trim().length() > 0) - props.put(LOS, new ThreadLockedOwnableSynchronizers(linesOfLOS)); - } - } catch (IOException e) { - e.printStackTrace(); - } + public Object getVal(String key) { + return props.get(key); } - public ThreadInfo(HashMap mtd) { - super(mtd); + public Object setVal(String key, Object val) { + return props.put(key, val); } - private void parseThreadState(String threadState) { - Pattern p = Pattern.compile("^[\\s]*" + JAVA_LANG_THREAD_STATE + ": (.*)$"); - Matcher m = p.matcher(threadState); - if (m.find()) { - props.put(STATE, m.group(1)); - } + public Set getProps() { + return props.keySet(); + } + + + public ThreadInfo(String stackTrace) { + props = new JStackTextualFormatParser().parseLegacyTextualFormat(stackTrace); } @@ -93,105 +67,8 @@ protected String metadataProperty(String metaLine, String propertyName) { return null; } - protected void metadataKeyValProperties(String metaLine) { - Pattern p = Pattern.compile("(\\S+)=(\\S+)"); // a nonspace string then = and then a non space string - Matcher m = p.matcher(metaLine); - while (m.find()) { - props.put(m.group(1), m.group(2)); - } - if (props.get(TID) != null && !props.get(TID).equals("*")) { - props.put(TID + "Long", new HexaLong((String) props.get(TID))); - } - if (props.get(NID) != null && !props.get(NID).equals("*")) { - props.put(NID + "Long", new HexaLong((String) props.get(NID))); - } - } - - private void parseMetaLine(String metaLine) { - Pattern p = Pattern.compile("^\"(.*)\".*"); - Matcher m = p.matcher(metaLine); - - if (m.find()) { - props.put(NAME, m.group(1)); - } - - extractStatus(metaLine); - metadataKeyValProperties(metaLine); - - if (metaLine.contains("\" " + DAEMON + " ")) { - props.put(DAEMON, true); - } - - } - - private void extractStatus(String metaLine) { - int idx = metaLine.lastIndexOf('='); - if (idx != -1) { - String lastParam = metaLine.substring(idx); - idx = lastParam.indexOf(' '); - if (idx != -1) { - - lastParam = lastParam.substring(idx + 1); - - if (lastParam.length() > 0) { - props.put(STATUS, lastParam.trim()); - } - } - } - } - @Override public String toString() { - - StringBuilder mdStr = new StringBuilder(); - - if (props.get(NAME) != null) { - mdStr.append("\"").append(props.get(NAME)).append("\""); - } - if (props.get(COUNT) != null) { - mdStr.append(" " + COUNT + "=").append(props.get(COUNT)); - } - if (props.get(DAEMON) != null) { - mdStr.append(" " + DAEMON); - } - if (props.get(PRIO) != null) { - mdStr.append(" " + PRIO + "=").append(props.get(PRIO)); - } - if (props.get(TID) != null) { - mdStr.append(" " + TID + "=" + props.get(TID)); - } - if (props.get(NID) != null) { - mdStr.append(" " + NID + "=" + props.get(NID)); - } - if (props.get(STATUS) != null) { - mdStr.append(" " + props.get(STATUS)); - } - if (props.get(CPUNS) != null) { - mdStr.append(" " + CPUNS + "=").append(props.get(CPUNS)); - } - if (props.get(WALL) != null) { - mdStr.append(" " + WALL + "=").append(props.get(WALL)); - } - if (props.get(CPU_PREC) != null) { - mdStr.append(" " + CPU_PREC + "=").append(props.get(CPU_PREC)); - } - - - if (props.get(STATE) != null) { - mdStr.append("\n " + JAVA_LANG_THREAD_STATE + ": ").append(props.get(STATE)); - } - - if (props.get(STACK) != null) { - mdStr.append("\n").append(props.get(STACK).toString()); - } - mdStr.append("\n"); - if (props.get(LOS) != null) { - mdStr.append("\n " + LOCKED_OWNABLE_SYNCHRONIZERS + ":\n").append( - props.get(LOS).toString()); - } - - return mdStr.toString(); - + return new JStackTextualFormatParser().toJStackFormat(props); } - } diff --git a/src/test/java/com/performizeit/mjprof/model/ProfileEntryHelperTest.java b/src/test/java/com/performizeit/mjprof/model/ProfileEntryHelperTest.java index 2eefbdd..7c022b7 100644 --- a/src/test/java/com/performizeit/mjprof/model/ProfileEntryHelperTest.java +++ b/src/test/java/com/performizeit/mjprof/model/ProfileEntryHelperTest.java @@ -40,7 +40,6 @@ public void testPipe() { assertEquals(p.indentation, 6); assertEquals(p.charType, ProfileEntryHelper.INDENT); assertEquals(p.description, "at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2273)"); - } @Test @@ -51,6 +50,5 @@ public void testLeaf() { assertEquals(10, p.indentation); assertEquals(p.charType, ProfileEntryHelper.LEAF); assertEquals(p.description, "at org.apache.hadoop.hdfs.DFSUtil.(DFSUtil.java:128)"); - } } diff --git a/src/test/java/com/performizeit/mjprof/model/ThreadInfoAggregatorTest.java b/src/test/java/com/performizeit/mjprof/model/ThreadInfoAggregatorTest.java index b1841f6..c6985cb 100644 --- a/src/test/java/com/performizeit/mjprof/model/ThreadInfoAggregatorTest.java +++ b/src/test/java/com/performizeit/mjprof/model/ThreadInfoAggregatorTest.java @@ -61,8 +61,6 @@ public void testTwo() { ThreadInfoAggregator a = new ThreadInfoAggregator(List.of(TID)); a.accumulateThreadInfo(new ThreadInfo(stack1)); a.accumulateThreadInfo(new ThreadInfo(stack2)); - System.out.println(a.getAggrInfos().get(0).toString()); - } @Test @@ -70,8 +68,6 @@ public void testTwoA() { ThreadInfoAggregator a = new ThreadInfoAggregator(List.of(TID)); a.accumulateThreadInfo(new ThreadInfo(stck1a)); a.accumulateThreadInfo(new ThreadInfo(stck2a)); - System.out.println(a.getAggrInfos().get(0).toString()); - } @Test @@ -80,7 +76,6 @@ public void testTwoB() { FileNameEliminator fne = new FileNameEliminator(); a.accumulateThreadInfo(fne.map(new ThreadInfo(stck1a))); a.accumulateThreadInfo(fne.map(new ThreadInfo(stck2a))); - System.out.println(a.getAggrInfos().get(0).toString()); - + // System.out.println(a.getAggrInfos().get(0).toString()); } } diff --git a/src/test/java/com/performizeit/mjprof/plugin/PluginWithDefaultConstructorTest.java b/src/test/java/com/performizeit/mjprof/plugin/PluginWithDefaultConstructorTest.java index 9099105..801c8a3 100644 --- a/src/test/java/com/performizeit/mjprof/plugin/PluginWithDefaultConstructorTest.java +++ b/src/test/java/com/performizeit/mjprof/plugin/PluginWithDefaultConstructorTest.java @@ -21,21 +21,21 @@ import com.performizeit.mjprof.api.Param; import com.performizeit.mjprof.parser.ThreadInfo; -@Plugin(name="test1", params = {@Param()}) +@Plugin(name = "test1", params = {@Param()}) public class PluginWithDefaultConstructorTest implements SingleThreadMapper { - private final String expr="kk"; + private final String expr = "kk"; - public ThreadInfo map(ThreadInfo stck) { - return stck; - } + public ThreadInfo map(ThreadInfo stck) { + return stck; + } - public ThreadInfo execute(ThreadInfo stck) { - return map(stck); - } - - public String getHelpLine() { - return "Trim"; - } + public ThreadInfo execute(ThreadInfo stck) { + return map(stck); + } + + public String getHelpLine() { + return "Trim"; + } } diff --git a/src/test/java/com/performizeit/mjprof/plugins/mappers/MergedCalleesTest.java b/src/test/java/com/performizeit/mjprof/plugins/mappers/MergedCalleesTest.java index 3fc42ac..339cddc 100644 --- a/src/test/java/com/performizeit/mjprof/plugins/mappers/MergedCalleesTest.java +++ b/src/test/java/com/performizeit/mjprof/plugins/mappers/MergedCalleesTest.java @@ -23,7 +23,7 @@ public void testName() throws Exception { ThreadDump dump = new ThreadDump(readFromFile("src/test/res/test2.txt")); // ThreadDump resDump = new ThreadDump(readFromFile("src/test/res/resTest2.txt")); -System.out.println(g.map(dump).getStacks()); +//System.out.println(g.map(dump).getStacks()); } diff --git a/src/test/java/com/performizeit/mjprof/plugins/mappers/StackElimTest.java b/src/test/java/com/performizeit/mjprof/plugins/mappers/StackElimTest.java index 870dc10..55725c9 100644 --- a/src/test/java/com/performizeit/mjprof/plugins/mappers/StackElimTest.java +++ b/src/test/java/com/performizeit/mjprof/plugins/mappers/StackElimTest.java @@ -26,11 +26,11 @@ public class StackElimTest { - String strt = """ + String threadHeader = """ "qtp188618231-14" prio=10 tid=0x0007fd8d8d5b000 nid=0xd17 waiting for monitor entry [0x00007fd8ae207000] java.lang.Thread.State: BLOCKED (on object monitor) """; - String stck = + String stackTrace = """ at org.apache.hadoop.hdfs.DFSUtil.(DFSUtil.java:128) at org.apache.hadoop.hdfs.DFSClient.(DFSClient.java:437) @@ -43,12 +43,12 @@ public class StackElimTest { at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:316) """; - String akkka = + String stackTraceWithPhrase = """ at com.akkka.aaa.bbbb.rest.FileSystemFactory.provide(FileSystemFactory.java:32) at com.akkka.aaa.bbb.rest.FileSystemFactory.provide(FlsFactory.java:44) """; - String stck2 = + String stackTracePart2 = """ at org.jvnet.hk2.internal.FactoryCreator.create(FactoryCreator.java:56) at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456) @@ -67,27 +67,25 @@ public class StackElimTest { @Test public void testStack() { - ThreadInfo js = new ThreadInfo(strt + stck + akkka + stck2); - - assertEquals(strt + stck + akkka + stck2, js.toString()); + ThreadInfo js = new ThreadInfo(threadHeader + stackTrace + stackTraceWithPhrase + stackTracePart2); + assertEquals(threadHeader + stackTrace + stackTraceWithPhrase + stackTracePart2, js.toString()); } @Test public void testKeep() { - ThreadInfo js = new ThreadInfo(strt + stck + akkka + stck2); + ThreadInfo js = new ThreadInfo(threadHeader + stackTrace + stackTraceWithPhrase + stackTracePart2); StackFrameContains tb = new StackFrameContains("com.akkka"); ThreadInfo js2 = tb.map(js); - assertEquals(strt + akkka, js2.toString()); + assertEquals(threadHeader + stackTraceWithPhrase, js2.toString()); } @Test public void testElim() { - ThreadInfo js = new ThreadInfo(strt + stck + akkka + stck2); + ThreadInfo js = new ThreadInfo(threadHeader + stackTrace + stackTraceWithPhrase + stackTracePart2); StackFrameNotContains tb = new StackFrameNotContains("com.akkka"); ThreadInfo js2 = tb.map(js); - assertEquals(strt + stck + stck2, js2.toString()); - + assertEquals(threadHeader + stackTrace + stackTracePart2, js2.toString()); } } diff --git a/src/test/java/com/performizeit/mjprof/plugins/mergers/StackTreeTest.java b/src/test/java/com/performizeit/mjprof/plugins/mergers/StackTreeTest.java index a7ea1ec..0ddc29e 100644 --- a/src/test/java/com/performizeit/mjprof/plugins/mergers/StackTreeTest.java +++ b/src/test/java/com/performizeit/mjprof/plugins/mergers/StackTreeTest.java @@ -27,7 +27,7 @@ public class StackTreeTest { static char sep = getSeparator(); - static String stck = + static String stackTrace = """ at org.apache.hadoop.hdfs.DFSUtil.(DFSUtil.java:128) @@ -77,14 +77,11 @@ public class StackTreeTest { @Test public void testConstructor() { - Profile st = new Profile(stck); - st.addMulti(new Profile(stck)); + Profile st = new Profile(stackTrace); + st.addMulti(new Profile(stackTrace)); st.addMulti(new Profile(stck2)); - // System.out.println(st.toString()); Profile st2 = new Profile(st.toString()); - // System.out.println(st2.toString()); assertEquals(st.toString(), st2.toString()); - // System.out.println(st2.toString()); assertEquals(tree, st2.toString()); }