blob: 25330023898b714f799bfbe1e4116fcb1269fa10 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2016 IBM Corporation and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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
*/
@Override
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();
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
*/
@Override
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) {
try (BufferedReader 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);
}
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;
}
}