/**
* jvmtop - java monitoring for the command-line
*
* Copyright (C) 2013 by Patric Rufflar. 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 program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.jvmtop.view;
import java.util.Iterator;
import com.jvmtop.monitor.VMInfo;
import com.jvmtop.monitor.VMInfoState;
import com.jvmtop.openjdk.tools.LocalVirtualMachine;
import com.jvmtop.profiler.CPUSampler;
import com.jvmtop.profiler.MethodStats;
/**
* CPU sampling-based profiler view which shows methods with top CPU usage.
*
* @author paru
*
*/
public class VMProfileView extends AbstractConsoleView
{
private CPUSampler cpuSampler_;
private VMInfo vmInfo_;
public VMProfileView(int vmid, Integer width) throws Exception
{
super(width);
LocalVirtualMachine localVirtualMachine = LocalVirtualMachine
.getLocalVirtualMachine(vmid);
vmInfo_ = VMInfo.processNewVM(localVirtualMachine, vmid);
cpuSampler_ = new CPUSampler(vmInfo_);
}
@Override
public void sleep(long millis) throws Exception
{
long cur = System.currentTimeMillis();
cpuSampler_.update();
while (cur + millis > System.currentTimeMillis())
{
cpuSampler_.update();
super.sleep(100);
}
}
@Override
public void printView() throws Exception
{
if (vmInfo_.getState() == VMInfoState.ATTACHED_UPDATE_ERROR)
{
System.out
.println("ERROR: Could not fetch telemetries - Process terminated?");
exit();
return;
}
if (vmInfo_.getState() != VMInfoState.ATTACHED)
{
System.out.println("ERROR: Could not attach to process.");
exit();
return;
}
int w = width - 40;
System.out.printf(" Profiling PID %d: %40s %n%n", vmInfo_.getId(),
leftStr(vmInfo_.getDisplayName(), w));
// these are the spaces taken up by the formatting, the rest is usable
// for printing out the method name
w = width - (1 + 6 + 3 + 9 + 3 + 2);
for (Iterator<MethodStats> iterator = cpuSampler_.getTop(20).iterator(); iterator
.hasNext();)
{
MethodStats stats = iterator.next();
double wallRatio = (double) stats.getHits().get()
/ cpuSampler_.getTotal() * 100;
if (!Double.isNaN(wallRatio))
{
System.out.printf(" %6.2f%% (%9.2fs) %s()%n", wallRatio, wallRatio
/ 100d
* cpuSampler_.getUpdateCount() * 0.1d,
shortFQN(stats.getClassName(), stats.getMethodName(), w));
}
}
}
/**
* Shortens a full qualified class name if it exceeds the size.
* TODO: improve method to shorten middle packages first,
* maybe abbreviating the package by its first character.
*
* @param fqn
* @param method
* @param size
* @return
*/
private String shortFQN(String fqn, String method, int size)
{
String line = fqn + "." + method;
if (line.length() > size)
{
line = "..." + line.substring(3, size);
}
return line;
}
}