add perfcounter command. #1029

This commit is contained in:
hengyunabc 2020-02-17 01:52:00 +08:00
parent 4e771e2a7d
commit f5f7583c98
8 changed files with 206 additions and 0 deletions

View File

@ -34,6 +34,7 @@ import com.taobao.arthas.core.command.monitor200.HeapDumpCommand;
import com.taobao.arthas.core.command.monitor200.JvmCommand;
import com.taobao.arthas.core.command.monitor200.MBeanCommand;
import com.taobao.arthas.core.command.monitor200.MonitorCommand;
import com.taobao.arthas.core.command.monitor200.PerfCounterCommand;
import com.taobao.arthas.core.command.monitor200.ProfilerCommand;
import com.taobao.arthas.core.command.monitor200.StackCommand;
import com.taobao.arthas.core.command.monitor200.ThreadCommand;
@ -78,6 +79,7 @@ public class BuiltinCommandPack implements CommandResolver {
commands.add(Command.create(WatchCommand.class));
commands.add(Command.create(TimeTunnelCommand.class));
commands.add(Command.create(JvmCommand.class));
commands.add(Command.create(PerfCounterCommand.class));
// commands.add(Command.create(GroovyScriptCommand.class));
commands.add(Command.create(OgnlCommand.class));
commands.add(Command.create(MemoryCompilerCommand.class));

View File

@ -0,0 +1,120 @@
package com.taobao.arthas.core.command.monitor200;
import static com.taobao.text.ui.Element.label;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import com.taobao.arthas.common.JavaVersionUtils;
import com.taobao.arthas.common.PidUtils;
import com.taobao.arthas.core.command.Constants;
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
import com.taobao.middleware.cli.annotations.Option;
import com.taobao.middleware.cli.annotations.Summary;
import com.taobao.middleware.logger.Logger;
import com.taobao.text.Decoration;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import sun.management.counter.Counter;
import sun.management.counter.perf.PerfInstrumentation;
/**
* @see sun.misc.Perf
* @see sun.management.counter.perf.PerfInstrumentation
* @author hengyunabc 2020-02-16
*/
@Name("perfcounter")
@Summary("Display the perf counter infornation.")
@Description(Constants.WIKI + Constants.WIKI_HOME + "perf")
public class PerfCounterCommand extends AnnotatedCommand {
private static final Logger logger = LogUtil.getArthasLogger();
private static Object perfObject;
private static Method attachMethod;
private boolean details;
@Option(shortName = "d", longName = "details", flag = true)
@Description("print all perf counter details")
public void setDetails(boolean details) {
this.details = details;
}
@Override
public void process(CommandProcess process) {
try {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
if (this.details) {
table = new TableElement(3, 1, 1, 10).leftCellPadding(1).rightCellPadding(1);
table.row(true, label("Name").style(Decoration.bold.bold()),
label("Variability").style(Decoration.bold.bold()),
label("Units").style(Decoration.bold.bold()), label("Value").style(Decoration.bold.bold()));
}
List<Counter> perfCounters = getPerfCounters();
if (perfCounters.isEmpty()) {
process.write(
"please check arthas log. if java version >=9 , try to add jvm options when start your process: "
+ "--add-opens java.base/jdk.internal.perf=ALL-UNNAMED "
+ "--add-exports java.base/jdk.internal.perf=ALL-UNNAMED\n");
} else {
for (Counter counter : perfCounters) {
if (details) {
table.row(counter.getName(), String.valueOf(counter.getVariability()),
String.valueOf(counter.getUnits()), String.valueOf(counter.getValue()));
} else {
table.row(counter.getName(), String.valueOf(counter.getValue()));
}
}
}
process.write(RenderUtil.render(table, process.width()));
} finally {
process.end();
}
}
private static List<Counter> getPerfCounters() {
/**
* <pre>
* Perf p = Perf.getPerf();
* ByteBuffer buffer = p.attach(pid, "r");
* </pre>
*/
try {
if (perfObject == null) {
// jdk8
String perfClassName = "sun.misc.Perf";
// jdk 11
if (!JavaVersionUtils.isLessThanJava9()) {
perfClassName = "jdk.internal.perf.Perf";
}
Class<?> perfClass = ClassLoader.getSystemClassLoader().loadClass(perfClassName);
Method getPerfMethod = perfClass.getDeclaredMethod("getPerf");
perfObject = getPerfMethod.invoke(null);
}
if (attachMethod == null) {
attachMethod = perfObject.getClass().getDeclaredMethod("attach",
new Class<?>[] { int.class, String.class });
}
ByteBuffer buffer = (ByteBuffer) attachMethod.invoke(perfObject,
new Object[] { (int) PidUtils.currentLongPid(), "r" });
PerfInstrumentation perfInstrumentation = new PerfInstrumentation(buffer);
return perfInstrumentation.getAllCounters();
} catch (Throwable e) {
logger.error("arthas", "get perf counter error", e);
}
return Collections.emptyList();
}
}

View File

@ -27,6 +27,7 @@
* [sysprop](sysprop.md)——查看和修改JVM的系统属性
* [sysenv](sysenv.md)——查看JVM的环境变量
* [vmoption](vmoption.md)——查看和修改JVM里诊断相关的option
* [perfcounter](perfcounter.md)——查看当前 JVM 的Perf Counter信息
* [logger](logger.md)——查看和修改logger
* [getstatic](getstatic.md)——查看类的静态属性
* [ognl](ognl.md)——执行ognl表达式

View File

@ -7,6 +7,7 @@
* [sysprop](sysprop.md)
* [sysenv](sysenv.md)
* [vmoption](vmoption.md)
* [perfcounter](perfcounter.md)
* [logger](logger.md)
* [mbean](mbean.md)
* [getstatic](getstatic.md)

View File

@ -25,6 +25,7 @@ Advanced Usage
* [sysprop](sysprop.md) - view/modify system properties
* [sysenv](sysenv.md) — view system environment variables
* [vmoption](vmoption.md) - view/modify the vm diagnostic options.
* [perfcounter](perfcounter.md) - show JVM Perf Counter information
* [logger](logger.md) - print the logger information, update the logger level
* [getstatic](getstatic.md) - examine class's static properties
* [ognl](ognl.md) - execute ongl expression

View File

@ -7,6 +7,7 @@ All Commands
* [sysprop](sysprop.md)
* [sysenv](sysenv.md)
* [vmoption](vmoption.md)
* [perfcounter](perfcounter.md)
* [logger](logger.md)
* [mbean](mbean.md)
* [getstatic](getstatic.md)

View File

@ -0,0 +1,40 @@
perfcounter
===
> Check the current JVM Perf Counter information.
### Usage
```
$ perfcounter
java.ci.totalTime 2325637411
java.cls.loadedClasses 3403
java.cls.sharedLoadedClasses 0
java.cls.sharedUnloadedClasses 0
java.cls.unloadedClasses 0
java.property.java.version 11.0.4
java.property.java.vm.info mixed mode
java.property.java.vm.name OpenJDK 64-Bit Server VM
...
```
Print more information with the `-d` option:
```
$ perfcounter -d
Name Variability Units Value
---------------------------------------------------------------------------------
java.ci.totalTime Monotonic Ticks 3242526906
java.cls.loadedClasses Monotonic Events 3404
java.cls.sharedLoadedClasses Monotonic Events 0
java.cls.sharedUnloadedClasses Monotonic Events 0
java.cls.unloadedClasses Monotonic Events 0
```
### JVM above JDK9
If the information is not printed, when the application starts, add the following parameters:
```
--add-opens java.base/jdk.internal.perf=ALL-UNNAMED --add-exports java.base/jdk.internal.perf=ALL-UNNAMED
```

View File

@ -0,0 +1,40 @@
perfcounter
===
> 查看当前JVM的 Perf Counter信息
### 使用参考
```
$ perfcounter
java.ci.totalTime 2325637411
java.cls.loadedClasses 3403
java.cls.sharedLoadedClasses 0
java.cls.sharedUnloadedClasses 0
java.cls.unloadedClasses 0
java.property.java.version 11.0.4
java.property.java.vm.info mixed mode
java.property.java.vm.name OpenJDK 64-Bit Server VM
...
```
可以用`-d`参数打印更多信息:
```
$ perfcounter -d
Name Variability Units Value
---------------------------------------------------------------------------------
java.ci.totalTime Monotonic Ticks 3242526906
java.cls.loadedClasses Monotonic Events 3404
java.cls.sharedLoadedClasses Monotonic Events 0
java.cls.sharedUnloadedClasses Monotonic Events 0
java.cls.unloadedClasses Monotonic Events 0
```
### jdk9以上的应用
如果没有打印出信息,应用在启动时,加下面的参数:
```
--add-opens java.base/jdk.internal.perf=ALL-UNNAMED --add-exports java.base/jdk.internal.perf=ALL-UNNAMED
```