in core/src/main/java/com/taobao/arthas/core/command/monitor200/ThreadSampler.java [34:155]
public List<ThreadVO> sample(Collection<ThreadVO> originThreads) {
List<ThreadVO> threads = new ArrayList<ThreadVO>(originThreads);
// Sample CPU
if (lastCpuTimes.isEmpty()) {
lastSampleTimeNanos = System.nanoTime();
for (ThreadVO thread : threads) {
if (thread.getId() > 0) {
long cpu = threadMXBean.getThreadCpuTime(thread.getId());
lastCpuTimes.put(thread, cpu);
thread.setTime(cpu / 1000000);
}
}
// add internal threads
Map<String, Long> internalThreadCpuTimes = getInternalThreadCpuTimes();
if (internalThreadCpuTimes != null) {
for (Map.Entry<String, Long> entry : internalThreadCpuTimes.entrySet()) {
String key = entry.getKey();
ThreadVO thread = createThreadVO(key);
thread.setTime(entry.getValue() / 1000000);
threads.add(thread);
lastCpuTimes.put(thread, entry.getValue());
}
}
//sort by time
Collections.sort(threads, new Comparator<ThreadVO>() {
@Override
public int compare(ThreadVO o1, ThreadVO o2) {
long l1 = o1.getTime();
long l2 = o2.getTime();
if (l1 < l2) {
return 1;
} else if (l1 > l2) {
return -1;
} else {
return 0;
}
}
});
return threads;
}
// Resample
long newSampleTimeNanos = System.nanoTime();
Map<ThreadVO, Long> newCpuTimes = new HashMap<ThreadVO, Long>(threads.size());
for (ThreadVO thread : threads) {
if (thread.getId() > 0) {
long cpu = threadMXBean.getThreadCpuTime(thread.getId());
newCpuTimes.put(thread, cpu);
}
}
// internal threads
Map<String, Long> newInternalThreadCpuTimes = getInternalThreadCpuTimes();
if (newInternalThreadCpuTimes != null) {
for (Map.Entry<String, Long> entry : newInternalThreadCpuTimes.entrySet()) {
ThreadVO threadVO = createThreadVO(entry.getKey());
threads.add(threadVO);
newCpuTimes.put(threadVO, entry.getValue());
}
}
// Compute delta time
final Map<ThreadVO, Long> deltas = new HashMap<ThreadVO, Long>(threads.size());
for (ThreadVO thread : newCpuTimes.keySet()) {
Long t = lastCpuTimes.get(thread);
if (t == null) {
t = 0L;
}
long time1 = t;
long time2 = newCpuTimes.get(thread);
if (time1 == -1) {
time1 = time2;
} else if (time2 == -1) {
time2 = time1;
}
long delta = time2 - time1;
deltas.put(thread, delta);
}
long sampleIntervalNanos = newSampleTimeNanos - lastSampleTimeNanos;
// Compute cpu usage
final HashMap<ThreadVO, Double> cpuUsages = new HashMap<ThreadVO, Double>(threads.size());
for (ThreadVO thread : threads) {
double cpu = sampleIntervalNanos == 0 ? 0 : (Math.rint(deltas.get(thread) * 10000.0 / sampleIntervalNanos) / 100.0);
cpuUsages.put(thread, cpu);
}
// Sort by CPU time : should be a rendering hint...
Collections.sort(threads, new Comparator<ThreadVO>() {
@Override
public int compare(ThreadVO o1, ThreadVO o2) {
long l1 = deltas.get(o1);
long l2 = deltas.get(o2);
if (l1 < l2) {
return 1;
} else if (l1 > l2) {
return -1;
} else {
return 0;
}
}
});
for (ThreadVO thread : threads) {
//nanos to mills
long timeMills = newCpuTimes.get(thread) / 1000000;
long deltaTime = deltas.get(thread) / 1000000;
double cpu = cpuUsages.get(thread);
thread.setCpu(cpu);
thread.setTime(timeMills);
thread.setDeltaTime(deltaTime);
}
lastCpuTimes = newCpuTimes;
lastSampleTimeNanos = newSampleTimeNanos;
return threads;
}