75990f8013
Reviewed-by: kvn, iignatyev
228 lines
7.5 KiB
Java
228 lines
7.5 KiB
Java
/*
|
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code 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
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
*/
|
|
|
|
package rtm;
|
|
|
|
import java.util.EnumMap;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.regex.Pattern;
|
|
import java.util.regex.Matcher;
|
|
|
|
/**
|
|
* Wrapper for +UsePreciseRTMLockingStatistics output.
|
|
*
|
|
* Example of locking statistics:
|
|
*
|
|
* java/lang/ClassLoader.loadClass@7
|
|
* # rtm locks total (estimated): 0
|
|
* # rtm lock aborts : 13
|
|
* # rtm lock aborts 0: 12
|
|
* # rtm lock aborts 1: 0
|
|
* # rtm lock aborts 2: 0
|
|
* # rtm lock aborts 3: 0
|
|
* # rtm lock aborts 4: 0
|
|
* # rtm lock aborts 5: 0
|
|
*/
|
|
public class RTMLockingStatistics {
|
|
/**
|
|
* Pattern for aborts per abort type entries.
|
|
*/
|
|
private static final Pattern ABORT_PATTERN;
|
|
|
|
/**
|
|
* Pattern for whole statistics.
|
|
*/
|
|
private static final Pattern RTM_LOCKING_STATISTICS_PATTERN;
|
|
|
|
static {
|
|
String abortRe
|
|
= "# rtm lock aborts\\s+(?<type>[0-9]+):\\s(?<count>[0-9]+)";
|
|
|
|
ABORT_PATTERN = Pattern.compile(abortRe);
|
|
RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile(
|
|
"(?<className>[^.\n]+)\\." +
|
|
"(?<methodName>[^@\n]+)@(?<bci>[0-9]+)\n" +
|
|
"# rtm locks total \\(estimated\\):\\s*" +
|
|
"(?<totalLocks>[0-9]+)\n" +
|
|
"# rtm lock aborts\\s+:\\s*(?<totalAborts>[0-9]+)\n" +
|
|
"(?<abortStats>(" + abortRe + "\n)+)");
|
|
}
|
|
|
|
private final long totalLocks;
|
|
private final long totalAborts;
|
|
private final String className;
|
|
private final String methodName;
|
|
private final int bci;
|
|
private final Map<AbortType, Long> aborts = new EnumMap<>(AbortType.class);
|
|
|
|
/**
|
|
* Constructs RTMLockingStatistics from matcher captured statistics entry.
|
|
* @param matcher Matcher captured statistics entry.
|
|
*/
|
|
private RTMLockingStatistics(Matcher matcher) {
|
|
className = matcher.group("className");
|
|
methodName = matcher.group("methodName");
|
|
bci = Integer.valueOf(matcher.group("bci"));
|
|
totalLocks = Long.valueOf(matcher.group("totalLocks"));
|
|
totalAborts = Long.valueOf(matcher.group("totalAborts"));
|
|
|
|
Matcher abortMatcher = ABORT_PATTERN.matcher(matcher.
|
|
group("abortStats"));
|
|
|
|
while (abortMatcher.find()) {
|
|
int type = Integer.valueOf(abortMatcher.group("type"));
|
|
long count = Long.valueOf(abortMatcher.group("count"));
|
|
setAborts(AbortType.lookup(type), count);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Parses string and return all founded RTM locking statistics entries.
|
|
*
|
|
* @param str the string to be parsed.
|
|
* @return list with all founded RTM locking statistics entries or
|
|
* empty list if nothing was found.
|
|
*/
|
|
public static List<RTMLockingStatistics> fromString(String str) {
|
|
List<RTMLockingStatistics> statistics = new LinkedList<>();
|
|
Matcher matcher = RTM_LOCKING_STATISTICS_PATTERN.matcher(str);
|
|
|
|
while (matcher.find()) {
|
|
RTMLockingStatistics lock = new RTMLockingStatistics(matcher);
|
|
statistics.add(lock);
|
|
}
|
|
|
|
return statistics;
|
|
}
|
|
|
|
/**
|
|
* Parses string and return all founded RTM locking statistics entries
|
|
* for locks in method {@code methodName}.
|
|
*
|
|
* @param methodName a name of the method for locks from which statistics
|
|
* should be gathered.
|
|
* @param str the string to be parsed.
|
|
* @return list with all founded RTM locking statistics entries or
|
|
* empty list if nothing was found.
|
|
*/
|
|
public static List<RTMLockingStatistics> fromString(String methodName,
|
|
String str) {
|
|
String formattedMethodName = formatMethodName(methodName);
|
|
|
|
List<RTMLockingStatistics> statisticsForMethod = new LinkedList<>();
|
|
for (RTMLockingStatistics statistics : fromString(str)) {
|
|
if (statistics.getLockName().startsWith(formattedMethodName)) {
|
|
statisticsForMethod.add(statistics);
|
|
}
|
|
}
|
|
return statisticsForMethod;
|
|
}
|
|
|
|
/**
|
|
* Formats method's name so it will have the same format as
|
|
* in rtm locking statistics.
|
|
*
|
|
* <pre>
|
|
* Example:
|
|
* com/example/Klass::method => com/example/Klass.method
|
|
* com/example/Klass.method => com/example/Klass.method
|
|
* com.example.Klass::method => com/example/Klass.method
|
|
* com.example.Klass.method => com/example/Klass.method
|
|
* </pre>
|
|
*
|
|
* @param methodName method's name that should be formatted.
|
|
* @return formatted method's name.
|
|
*/
|
|
private static String formatMethodName(String methodName) {
|
|
String m[];
|
|
if (methodName.contains("::")) {
|
|
m = methodName.split("::");
|
|
} else {
|
|
int splitAt = methodName.lastIndexOf('.');
|
|
m = new String[2];
|
|
m[0] = methodName.substring(0, splitAt);
|
|
m[1] = methodName.substring(splitAt + 1);
|
|
}
|
|
return String.format("%s.%s", m[0].replaceAll("\\.", "/"), m[1]);
|
|
}
|
|
|
|
/**
|
|
* Returns name of lock for which this statistics was collected.
|
|
* Lock name has following format:
|
|
* <class name>.<method name>@<bci>
|
|
*
|
|
* @return name of lock.
|
|
*/
|
|
public String getLockName() {
|
|
return String.format("%s.%s@%d", className, methodName, bci);
|
|
}
|
|
|
|
/**
|
|
* Returns aborts count for specified abort type.
|
|
*
|
|
* @param type an abort type.
|
|
* @return count of aborts.
|
|
*/
|
|
public long getAborts(AbortType type) {
|
|
return aborts.getOrDefault(type, 0L);
|
|
}
|
|
|
|
/**
|
|
* Sets aborts count for specified abort type.
|
|
*
|
|
* @param type an abort type.
|
|
* @param count count of aborts.
|
|
*/
|
|
public void setAborts(AbortType type, long count) {
|
|
aborts.put(type, count);
|
|
}
|
|
|
|
public long getTotalLocks() {
|
|
return totalLocks;
|
|
}
|
|
|
|
public long getTotalAborts() {
|
|
return totalAborts;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.append(getLockName()).append('\n');
|
|
builder.append(String.format("# rtm locks total (estimated): %d\n",
|
|
getTotalLocks()));
|
|
builder.append(String.format("# rtm lock aborts: %d\n",
|
|
getTotalLocks()));
|
|
|
|
for (AbortType type : AbortType.values()) {
|
|
builder.append(String.format("# rtm lock aborts %s %d\n",
|
|
type.toString(), getAborts(type)));
|
|
}
|
|
return builder.toString();
|
|
}
|
|
}
|