Skip to content

Commit

Permalink
Merge branch 'alibaba:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Fatpandac authored Aug 23, 2023
2 parents 0569487 + 1c41bcd commit 0227c36
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 64 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ pom.xml.versionsBackup
**/.flattened-pom.xml
**/.idea/**
**/cmake-build-debug/**

# VSCode
.vscode/
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,11 @@ public void process(CommandProcess process) {
}

if (all) {
processAllClasses(process, inst);
String hashCode = this.hashCode;
if (StringUtils.isBlank(hashCode) && targetClassLoader != null) {
hashCode = "" + Integer.toHexString(targetClassLoader.hashCode());
}
processAllClasses(process, inst, hashCode);
} else if (classLoaderSpecified && resource != null) {
processResources(process, inst, targetClassLoader);
} else if (classLoaderSpecified && this.loadClass != null) {
Expand Down Expand Up @@ -305,7 +309,7 @@ private void processLoadClass(CommandProcess process, Instrumentation inst, Clas
process.end();
}

private void processAllClasses(CommandProcess process, Instrumentation inst) {
private void processAllClasses(CommandProcess process, Instrumentation inst,String hashCode) {
RowAffect affect = new RowAffect();
getAllClasses(hashCode, inst, affect, process);
if (checkInterrupted(process)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
+ " profiler list # list all supported events\n"
+ " profiler actions # list all supported actions\n"
+ " profiler start --event alloc\n"
+ " profiler stop --format html # output file format, support html,jfr\n"
+ " profiler stop --format html # output file format, support flat[=N]|traces[=N]|collapsed|flamegraph|tree|jfr\n"
+ " profiler stop --file /tmp/result.html\n"
+ " profiler stop --threads \n"
+ " profiler start --include 'java/*' --include 'com/demo/*' --exclude '*Unsafe.park*'\n"
Expand Down Expand Up @@ -94,6 +94,26 @@ public class ProfilerCommand extends AnnotatedCommand {
*/
private boolean threads;

/**
* use simple class names instead of FQN
*/
private boolean simple;

/**
* print method signatures
*/
private boolean sig;

/**
* annotate Java methods
*/
private boolean ann;

/**
* prepend library names
*/
private boolean lib;

/**
* include only kernel-mode events
*/
Expand All @@ -119,6 +139,27 @@ public class ProfilerCommand extends AnnotatedCommand {
*/
private List<String> excludes;


/**
* FlameGraph title
*/
private String title;

/**
* FlameGraph minimum frame width in percent
*/
private String minwidth;

/**
* generate stack-reversed FlameGraph / Call tree
*/
private boolean reverse;

/**
* count the total value (time, bytes, etc.) instead of samples
*/
private boolean total;

private static String libPath;
private static AsyncProfiler profiler = null;

Expand Down Expand Up @@ -184,15 +225,18 @@ public void setFramebuf(long framebuf) {
}

@Option(shortName = "f", longName = "file")
@Description("dump output to <filename>")
@Description("dump output to <filename>, if ends with html or jfr, content format can be infered")
public void setFile(String file) {
this.file = file;
}

@Option(longName = "format")
@Description("dump output file format(html, jfr), default valut is html")
@DefaultValue("html")
@Option(shortName = "o", longName = "format")
@Description("dump output content format(flat[=N]|traces[=N]|collapsed|flamegraph|tree|jfr)")
public void setFormat(String format) {
// only for backward compatibility
if ("html".equals(format)) {
format = "flamegraph";
}
this.format = format;
}

Expand All @@ -209,6 +253,30 @@ public void setThreads(boolean threads) {
this.threads = threads;
}

@Option(shortName = "s", flag = true)
@Description("use simple class names instead of FQN")
public void setSimple(boolean simple) {
this.simple = simple;
}

@Option(shortName = "g", flag = true)
@Description("print method signatures")
public void setSig(boolean sig) {
this.sig = sig;
}

@Option(shortName = "a", flag = true)
@Description("annotate Java methods")
public void setAnn(boolean ann) {
this.ann = ann;
}

@Option(shortName = "l", flag = true)
@Description("prepend library names")
public void setLib(boolean lib) {
this.lib = lib;
}

@Option(longName = "allkernel", flag = true)
@Description("include only kernel-mode events")
public void setAllkernel(boolean allkernel) {
Expand All @@ -227,18 +295,50 @@ public void setDuration(long duration) {
this.duration = duration;
}

@Option(longName = "include")
@Option(shortName = "I", longName = "include")
@Description("include stack traces containing PATTERN, for example: 'java/*'")
public void setInclude(List<String> includes) {
this.includes = includes;
}

@Option(longName = "exclude")
@Option(shortName = "X", longName = "exclude")
@Description("exclude stack traces containing PATTERN, for example: '*Unsafe.park*'")
public void setExclude(List<String> excludes) {
this.excludes = excludes;
}

@Option(longName = "title")
@Description("FlameGraph title")
public void setTitle(String title) {
// escape HTML special characters
// and escape comma to avoid conflicts with JVM TI
title = title.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;")
.replace("'", "&apos;")
.replace(",", "&#44;");
this.title = title;
}

@Option(longName = "minwidth")
@Description("FlameGraph minimum frame width in percent")
public void setMinwidth(String minwidth) {
this.minwidth = minwidth;
}

@Option(longName = "reverse", flag = true)
@Description("generate stack-reversed FlameGraph / Call tree")
public void setReverse(boolean reverse) {
this.reverse = reverse;
}

@Option(longName = "total", flag = true)
@Description("count the total value (time, bytes, etc.) instead of samples")
public void setTotal(boolean total) {
this.total = total;
}

private AsyncProfiler profilerInstance() {
if (profiler != null) {
return profiler;
Expand Down Expand Up @@ -281,14 +381,16 @@ private AsyncProfiler profilerInstance() {
}

/**
* https://github.com/jvm-profiling-tools/async-profiler/blob/v2.5/src/arguments.cpp#L50
*
* https://github.com/async-profiler/async-profiler/blob/v2.9/profiler.sh#L154
*/
public enum ProfilerAction {
execute, start, stop, resume, list, version, status, load,
// start, resume, stop, dump, check, status, meminfo, list, collect,
start, resume, stop, dump, status, meminfo, list,
version,

load,
execute,
dumpCollapsed, dumpFlat, dumpTraces, getSamples,

actions
}

Expand All @@ -306,6 +408,9 @@ private String executeArgs(ProfilerAction action) {
if (this.file != null) {
sb.append("file=").append(this.file).append(',');
}
if (this.format != null) {
sb.append(this.format).append(',');
}
if (this.interval != null) {
sb.append("interval=").append(this.interval).append(',');
}
Expand All @@ -315,6 +420,18 @@ private String executeArgs(ProfilerAction action) {
if (this.threads) {
sb.append("threads").append(',');
}
if (this.simple) {
sb.append("simple").append(",");
}
if (this.sig) {
sb.append("sig").append(",");
}
if (this.ann) {
sb.append("ann").append(",");
}
if (this.lib) {
sb.append("lib").append(",");
}
if (this.allkernel) {
sb.append("allkernel").append(',');
}
Expand All @@ -332,6 +449,19 @@ private String executeArgs(ProfilerAction action) {
}
}

if (this.title != null) {
sb.append("title=").append(this.title).append(',');
}
if (this.minwidth != null) {
sb.append("minwidth=").append(this.minwidth).append(',');
}
if (this.reverse) {
sb.append("reverse").append(',');
}
if (this.total) {
sb.append("total").append(',');
}

return sb.toString();
}

Expand Down Expand Up @@ -385,7 +515,7 @@ public void run() {
//在异步线程执行,profiler命令已经结束,不能输出到客户端
try {
logger.info("stopping profiler ...");
ProfilerModel model = processStop(asyncProfiler);
ProfilerModel model = processStop(asyncProfiler, ProfilerAction.stop);
logger.info("profiler output file: " + model.getOutputFile());
logger.info("stop profiler successfully.");
} catch (Throwable e) {
Expand All @@ -396,20 +526,22 @@ public void run() {
}
process.appendResult(profilerModel);
} else if (ProfilerAction.stop.equals(profilerAction)) {
ProfilerModel profilerModel = processStop(asyncProfiler);
ProfilerModel profilerModel = processStop(asyncProfiler, profilerAction);
process.appendResult(profilerModel);
} else if (ProfilerAction.dump.equals(profilerAction)) {
ProfilerModel profilerModel = processStop(asyncProfiler, profilerAction);
process.appendResult(profilerModel);
} else if (ProfilerAction.resume.equals(profilerAction)) {
String executeArgs = executeArgs(ProfilerAction.resume);
String result = execute(asyncProfiler, executeArgs);
appendExecuteResult(process, result);
} else if (ProfilerAction.list.equals(profilerAction)) {
String result = asyncProfiler.execute("list");
appendExecuteResult(process, result);
} else if (ProfilerAction.version.equals(profilerAction)) {
String result = asyncProfiler.execute("version");
String result = asyncProfiler.execute("version=full");
appendExecuteResult(process, result);
} else if (ProfilerAction.status.equals(profilerAction)) {
String result = asyncProfiler.execute("status");
} else if (ProfilerAction.status.equals(profilerAction)
|| ProfilerAction.meminfo.equals(profilerAction)
|| ProfilerAction.list.equals(profilerAction)) {
String result = asyncProfiler.execute(profilerAction.toString());
appendExecuteResult(process, result);
} else if (ProfilerAction.dumpCollapsed.equals(profilerAction)) {
if (actionArg == null) {
Expand Down Expand Up @@ -448,9 +580,9 @@ public void run() {
}
}

private ProfilerModel processStop(AsyncProfiler asyncProfiler) throws IOException {
private ProfilerModel processStop(AsyncProfiler asyncProfiler, ProfilerAction profilerAction) throws IOException {
String outputFile = outputFile();
String executeArgs = executeArgs(ProfilerAction.stop);
String executeArgs = executeArgs(profilerAction);
String result = execute(asyncProfiler, executeArgs);

ProfilerModel profilerModel = createProfilerModel(result);
Expand All @@ -460,18 +592,40 @@ private ProfilerModel processStop(AsyncProfiler asyncProfiler) throws IOExceptio

private String outputFile() throws IOException {
if (this.file == null) {
String fileExt = outputFileExt();
File outputPath = ArthasBootstrap.getInstance().getOutputPath();
if (outputPath != null) {
this.file = new File(outputPath,
new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + "." + this.format)
new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + "." + fileExt)
.getAbsolutePath();
} else {
this.file = File.createTempFile("arthas-output", "." + this.format).getAbsolutePath();
this.file = File.createTempFile("arthas-output", "." + fileExt).getAbsolutePath();
}
}
return file;
}

/**
* This method should only be called when {@code this.file == null} is true.
*/
private String outputFileExt() {
String fileExt = "";
if (this.format == null) {
fileExt = "html";
} else if (this.format.startsWith("flat") || this.format.startsWith("traces")
|| this.format.equals("collapsed")) {
fileExt = "txt";
} else if (this.format.equals("flamegraph") || this.format.equals("tree")) {
fileExt = "html";
} else if (this.format.equals("jfr")) {
fileExt = "jfr";
} else {
// illegal -o option makes async-profiler use flat
fileExt = "txt";
}
return fileExt;
}

private void appendExecuteResult(CommandProcess process, String result) {
ProfilerModel profilerModel = createProfilerModel(result);
process.appendResult(profilerModel);
Expand Down
Loading

1 comment on commit 0227c36

@vercel
Copy link

@vercel vercel bot commented on 0227c36 Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.