CPUSampler.java
上传用户:gwt600
上传日期:2021-06-03
资源大小:704k
文件大小:9k
- /*
- This file is part of the OdinMS Maple Story Server
- Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- package net.sf.odinms.tools.performance;
- import java.io.IOException;
- import java.io.Writer;
- import java.lang.Thread.State;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.Map.Entry;
- public class CPUSampler {
- private List<String> included = new LinkedList<String>();
- private static CPUSampler instance = new CPUSampler();
- private long interval = 5;
- private SamplerThread sampler = null;
- private Map<StackTrace, Integer> recorded = new HashMap<StackTrace, Integer>();
- private int totalSamples = 0;
-
- private CPUSampler() {
-
- }
-
- public static CPUSampler getInstance() {
- return instance;
- }
-
- public void setInterval(long millis) {
- interval = millis;
- }
-
- public void addIncluded(String include) {
- for (String alreadyIncluded : included) {
- if (include.startsWith(alreadyIncluded)) {
- return;
- }
- }
- included.add(include);
- }
-
- public void reset() {
- recorded.clear();
- totalSamples = 0;
- }
-
- public void start() {
- if (sampler == null) {
- sampler = new SamplerThread();
- sampler.start();
- }
- }
-
- public void stop() {
- if (sampler != null) {
- sampler.stop();
- sampler = null;
- }
- }
-
- public SampledStacktraces getTopConsumers() {
- List<StacktraceWithCount> ret = new ArrayList<StacktraceWithCount>();
- Set<Entry<StackTrace, Integer>> entrySet = recorded.entrySet();
- for (Entry<StackTrace, Integer> entry : entrySet) {
- ret.add(new StacktraceWithCount(entry.getValue(), entry.getKey()));
- }
- Collections.sort(ret);
- return new SampledStacktraces(ret, totalSamples);
- }
-
- public void save(Writer writer, int minInvocations, int topMethods) throws IOException {
- SampledStacktraces topConsumers = getTopConsumers();
- StringBuilder builder = new StringBuilder(); // build our summary :o
- builder.append("Top Methods:n");
- for (int i = 0; i < topMethods && i < topConsumers.getTopConsumers().size(); i++) {
- builder.append(topConsumers.getTopConsumers().get(i).toString(topConsumers.getTotalInvocations(), 1));
- }
- builder.append("nStack Traces:n");
- writer.write(builder.toString());
- writer.write(topConsumers.toString(minInvocations));
- writer.flush();
- }
-
- private void consumeStackTraces(Map<Thread, StackTraceElement[]> traces) {
- for (Entry<Thread, StackTraceElement[]> trace : traces.entrySet()) {
- int relevant = findRelevantElement(trace.getValue());
- if (relevant != -1) {
- StackTrace st = new StackTrace(trace.getValue(), relevant, trace.getKey().getState());
- Integer i = recorded.get(st);
- totalSamples++;
- if (i == null) {
- recorded.put(st, Integer.valueOf(1));
- } else {
- recorded.put(st, Integer.valueOf(i.intValue() + 1));
- }
- }
- }
- }
-
- private int findRelevantElement(StackTraceElement[] trace) {
- if (trace.length == 0) {
- return -1;
- } else if (included.size() == 0) {
- return 0;
- }
- int firstIncluded = -1;
- for (String myIncluded : included) {
- for (int i = 0; i < trace.length; i++) {
- StackTraceElement ste = trace[i];
- if (ste.getClassName().startsWith(myIncluded)) {
- if (i < firstIncluded || firstIncluded == -1) {
- firstIncluded = i;
- break;
- }
- }
- }
- }
- if (firstIncluded >= 0 && trace[firstIncluded].getClassName().equals("net.sf.odinms.tools.performance.CPUSampler$SamplerThread")) { // don't sample us
- return -1;
- }
- return firstIncluded;
- }
-
- private static class StackTrace {
- private StackTraceElement[] trace;
- private State state;
-
- public StackTrace(StackTraceElement[] trace, int startAt, State state) {
- this.state = state;
- if (startAt == 0) {
- this.trace = trace;
- } else {
- this.trace = new StackTraceElement[trace.length - startAt];
- System.arraycopy(trace, startAt, this.trace, 0, this.trace.length);
- }
- }
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof StackTrace)) {
- return false;
- }
- StackTrace other = (StackTrace) obj;
- if (other.trace.length != trace.length) {
- return false;
- }
- if (!(other.state == this.state)) {
- return false;
- }
- for (int i = 0; i < trace.length; i++) {
- if (!trace[i].equals(other.trace[i])) {
- return false;
- }
- }
- return true;
- }
- @Override
- public int hashCode() {
- int ret = 13 * trace.length + state.hashCode();
- for (StackTraceElement ste : trace) {
- ret ^= ste.hashCode();
- }
- return ret;
- }
- public StackTraceElement[] getTrace() {
- return trace;
- }
- @Override
- public String toString() {
- return toString(-1);
- }
- public String toString(int traceLength) {
- StringBuilder ret = new StringBuilder("State: ");
- ret.append(state.name());
- if (traceLength > 1) {
- ret.append("n");
- } else {
- ret.append(" ");
- }
- int i = 0;
- for (StackTraceElement ste : trace) {
- i++;
- if (i > traceLength) {
- break;
- }
- ret.append(ste.getClassName());
- ret.append("#");
- ret.append(ste.getMethodName());
- ret.append(" (Line: ");
- ret.append(ste.getLineNumber());
- ret.append(")n");
- }
- return ret.toString();
- }
- }
-
- private class SamplerThread implements Runnable {
- private boolean running = false;
- private boolean shouldRun = false;
- private Thread rthread;
-
- public void start() {
- if (!running) {
- shouldRun = true;
- rthread = new Thread(this, "CPU Sampling Thread");
- rthread.start();
- running = true;
- }
- }
-
- public void stop() {
- this.shouldRun = false;
- rthread.interrupt();
- try {
- rthread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void run() {
- while (shouldRun) {
- consumeStackTraces(Thread.getAllStackTraces());
- try {
- Thread.sleep(interval);
- } catch (InterruptedException e) {
- return;
- }
- }
- }
- }
-
- public static class StacktraceWithCount implements Comparable<StacktraceWithCount> {
- private int count;
- private StackTrace trace;
-
- public StacktraceWithCount(int count, StackTrace trace) {
- super();
- this.count = count;
- this.trace = trace;
- }
- public int getCount() {
- return count;
- }
- public StackTraceElement[] getTrace() {
- return trace.getTrace();
- }
- @Override
- public int compareTo(StacktraceWithCount o) {
- return -Integer.valueOf(count).compareTo(Integer.valueOf(o.count));
- }
-
- @Override
- public String toString() {
- return count + " Sampled Invocationsn" + trace.toString();
- }
-
- private double getPercentage(int total) {
- return Math.round((((double) count) / total) * 10000.0) / 100.0;
- }
-
- public String toString(int totalInvoations, int traceLength) {
- return count + "/" + totalInvoations + " Sampled Invocations (" + getPercentage(totalInvoations) + "%) " +
- trace.toString(traceLength);
- }
- }
-
- public static class SampledStacktraces {
- List<StacktraceWithCount> topConsumers;
- int totalInvocations;
-
- public SampledStacktraces(List<StacktraceWithCount> topConsumers, int totalInvocations) {
- super();
- this.topConsumers = topConsumers;
- this.totalInvocations = totalInvocations;
- }
- public List<StacktraceWithCount> getTopConsumers() {
- return topConsumers;
- }
- public int getTotalInvocations() {
- return totalInvocations;
- }
-
- @Override
- public String toString() {
- return toString(0);
- }
-
- public String toString(int minInvocation) {
- StringBuilder ret = new StringBuilder();
- for (StacktraceWithCount swc : topConsumers) {
- if (swc.getCount() >= minInvocation) {
- ret.append(swc.toString(totalInvocations, Integer.MAX_VALUE));
- ret.append("n");
- }
- }
- return ret.toString();
- }
- }
- }