/*******************************************************************************
* Copyright (c) 2003, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.test.internal.performance;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.StringTokenizer;
class PerformanceMonitorLinux extends PerformanceMonitor {
private static long PAGESIZE= 4096;
private static long JIFFIES= 10L;
private static boolean fgHasElapsedTime= true;
private static long fgStartupTime;
/**
* Write out operating system counters for Linux.
* @param scalars
*/
protected void collectOperatingSystemCounters(Map scalars) {
synchronized(this) {
/**
* The status values for a Linux process, that is the values that come from /proc/self/stat.
* The names of the variables match the man proc page.
*/
StringTokenizer st= readTokens("/proc/self/stat", false); //$NON-NLS-1$
if (st != null) {
st.nextToken(); // int pid; // Process id.
st.nextToken(); // String comm; // The command name.
st.nextToken(); // String state;
st.nextToken(); // int ppid; // Parent process id. */
st.nextToken(); // int pgrp; // Process group. */
st.nextToken(); // int session;
st.nextToken(); // int ttry_nr;
st.nextToken(); // int tpgid;
st.nextToken(); // long flags;
long minflt = Long.parseLong(st.nextToken()); // Minor page faults (didn't need to load a page from disk). */
st.nextToken(); // long cminflt; // Minor page faults for the process and it's children. */
long majflt = Long.parseLong(st.nextToken()); // Major page faults. */
st.nextToken(); // long cmajflt; // Major page faults for the process and it's children. */
long utime = Long.parseLong(st.nextToken()); // User time in jiffies. */
long stime = Long.parseLong(st.nextToken()); // System time in jiffies. */
st.nextToken(); // long cutime; // User time for the process and it's children. */
st.nextToken(); // long cstime; // System time for the process and it's children. */
//addScalar(scalars, InternalDimensions.USER_TIME, utime*JIFFIES);
addScalar(scalars, InternalDimensions.KERNEL_TIME, stime*JIFFIES);
addScalar(scalars, InternalDimensions.CPU_TIME, (utime+stime)*JIFFIES);
addScalar(scalars, InternalDimensions.SOFT_PAGE_FAULTS, minflt);
addScalar(scalars, InternalDimensions.HARD_PAGE_FAULTS, majflt);
}
/**
* The status memory values values for a Linux process, that is the values that come from /proc/self/statm.
* The names of the variables match the man proc page.
*/
st= readTokens("/proc/self/statm", false); //$NON-NLS-1$
if (st != null) {
st.nextToken(); // int size; // Size of the process in pages
int resident= Integer.parseInt(st.nextToken()); // Resident size in pages.
st.nextToken(); // int shared; // Shared size in pages.
int trs= Integer.parseInt(st.nextToken()); // Text (code) size in pages.
int drs= Integer.parseInt(st.nextToken()); // Data/Stack size in pages.
int lrs= Integer.parseInt(st.nextToken()); // Library size in pages.
// st.nextToken(); // int dt; // Dirty pages.
addScalar(scalars, InternalDimensions.WORKING_SET, resident*PAGESIZE);
addScalar(scalars, InternalDimensions.TRS, trs*PAGESIZE);
addScalar(scalars, InternalDimensions.DRS, drs*PAGESIZE);
addScalar(scalars, InternalDimensions.LRS, lrs*PAGESIZE);
}
long currentTime= System.currentTimeMillis();
if (!PerformanceTestPlugin.isOldDB())
addScalar(scalars, InternalDimensions.SYSTEM_TIME, currentTime);
if (fgHasElapsedTime) {
if (fgStartupTime == 0) {
String t= System.getProperty("eclipse.startTime"); //$NON-NLS-1$
if (t != null) {
try {
fgStartupTime= Long.parseLong(t);
} catch (NumberFormatException e) {
fgHasElapsedTime= false;
}
} else
fgHasElapsedTime= false;
}
if (fgHasElapsedTime)
addScalar(scalars, InternalDimensions.ELAPSED_PROCESS, currentTime-fgStartupTime);
}
super.collectOperatingSystemCounters(scalars);
}
}
/**
* Write out the global machine counters for Linux.
* @param scalars
*/
protected void collectGlobalPerformanceInfo(Map scalars) {
synchronized(this) {
/**
* The meminfo values for a Linux machine, that is the values that come from /proc/meminfo.
*/
// /proc/meminfo is formatted on linux - use byte-counted output from free
StringTokenizer st= readOutput("free -b", true); //$NON-NLS-1$
if (st != null) {
st.nextToken(); // throw away label
long total= Long.parseLong(st.nextToken());
long used= Long.parseLong(st.nextToken());
long free= Long.parseLong(st.nextToken());
st.nextToken(); // long shared;
long buffers= Long.parseLong(st.nextToken());
long cache= Long.parseLong(st.nextToken());
addScalar(scalars, InternalDimensions.PHYSICAL_TOTAL, total);
addScalar(scalars, InternalDimensions.USED_LINUX_MEM, used);
addScalar(scalars, InternalDimensions.FREE_LINUX_MEM, free);
addScalar(scalars, InternalDimensions.BUFFERS_LINUX, buffers);
addScalar(scalars, InternalDimensions.SYSTEM_CACHE, cache);
}
super.collectGlobalPerformanceInfo(scalars);
}
}
private StringTokenizer readTokens(String procPath, boolean skipFirst) {
BufferedReader rdr= null;
try {
rdr= new BufferedReader(new FileReader(procPath));
if (skipFirst)
rdr.readLine(); // throw away the heading line
return new StringTokenizer(rdr.readLine());
} catch (IOException e) {
PerformanceTestPlugin.log(e);
} finally {
try {
if (rdr != null)
rdr.close();
} catch (IOException e) {
// silently ignored
}
}
return null;
}
private StringTokenizer readOutput(String cmd, boolean skipFirst) {
BufferedReader rdr= null;
try {
Process process= Runtime.getRuntime().exec(cmd);
rdr= new BufferedReader(new InputStreamReader(process.getInputStream()));
if (skipFirst)
rdr.readLine(); // throw away the heading line
return new StringTokenizer(rdr.readLine());
} catch (IOException e) {
PerformanceTestPlugin.log(e);
} finally {
try {
if (rdr != null)
rdr.close();
} catch (IOException e) {
// silently ignored
}
}
return null;
}
}