blob: 2007ab32e75327054f17b0332e30984e32cfc322 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.util;
import java.io.IOException;
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.util.Shell.ShellCommandExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Plugin to calculate resource information on Windows systems.
*/
@InterfaceAudience.Private
@InterfaceStability.Evolving
public class SysInfoWindows extends SysInfo {
private static final Logger LOG =
LoggerFactory.getLogger(SysInfoWindows.class);
private long vmemSize;
private long memSize;
private long vmemAvailable;
private long memAvailable;
private int numProcessors;
private long cpuFrequencyKhz;
private long cumulativeCpuTimeMs;
private float cpuUsage;
private long storageBytesRead;
private long storageBytesWritten;
private long netBytesRead;
private long netBytesWritten;
private long lastRefreshTime;
static final int REFRESH_INTERVAL_MS = 1000;
public SysInfoWindows() {
lastRefreshTime = 0;
reset();
}
@VisibleForTesting
long now() {
return Time.monotonicNow();
}
void reset() {
vmemSize = -1;
memSize = -1;
vmemAvailable = -1;
memAvailable = -1;
numProcessors = -1;
cpuFrequencyKhz = -1;
cumulativeCpuTimeMs = -1;
cpuUsage = -1;
storageBytesRead = -1;
storageBytesWritten = -1;
netBytesRead = -1;
netBytesWritten = -1;
}
String getSystemInfoInfoFromShell() {
try {
ShellCommandExecutor shellExecutor = new ShellCommandExecutor(
new String[] {Shell.getWinUtilsFile().getCanonicalPath(),
"systeminfo" });
shellExecutor.execute();
return shellExecutor.getOutput();
} catch (IOException e) {
LOG.error(StringUtils.stringifyException(e));
}
return null;
}
void refreshIfNeeded() {
long now = now();
if (now - lastRefreshTime > REFRESH_INTERVAL_MS) {
long refreshInterval = now - lastRefreshTime;
lastRefreshTime = now;
long lastCumCpuTimeMs = cumulativeCpuTimeMs;
reset();
String sysInfoStr = getSystemInfoInfoFromShell();
if (sysInfoStr != null) {
final int sysInfoSplitCount = 11;
int index = sysInfoStr.indexOf("\r\n");
if (index >= 0) {
String[] sysInfo = sysInfoStr.substring(0, index).split(",");
if (sysInfo.length == sysInfoSplitCount) {
try {
vmemSize = Long.parseLong(sysInfo[0]);
memSize = Long.parseLong(sysInfo[1]);
vmemAvailable = Long.parseLong(sysInfo[2]);
memAvailable = Long.parseLong(sysInfo[3]);
numProcessors = Integer.parseInt(sysInfo[4]);
cpuFrequencyKhz = Long.parseLong(sysInfo[5]);
cumulativeCpuTimeMs = Long.parseLong(sysInfo[6]);
storageBytesRead = Long.parseLong(sysInfo[7]);
storageBytesWritten = Long.parseLong(sysInfo[8]);
netBytesRead = Long.parseLong(sysInfo[9]);
netBytesWritten = Long.parseLong(sysInfo[10]);
if (lastCumCpuTimeMs != -1) {
/**
* This number will be the aggregated usage across all cores in
* [0.0, 100.0]. For example, it will be 400.0 if there are 8
* cores and each of them is running at 50% utilization.
*/
cpuUsage = (cumulativeCpuTimeMs - lastCumCpuTimeMs)
* 100F / refreshInterval;
}
} catch (NumberFormatException nfe) {
LOG.warn("Error parsing sysInfo", nfe);
}
} else {
LOG.warn("Expected split length of sysInfo to be "
+ sysInfoSplitCount + ". Got " + sysInfo.length);
}
} else {
LOG.warn("Wrong output from sysInfo: " + sysInfoStr);
}
}
}
}
/** {@inheritDoc} */
@Override
public long getVirtualMemorySize() {
refreshIfNeeded();
return vmemSize;
}
/** {@inheritDoc} */
@Override
public long getPhysicalMemorySize() {
refreshIfNeeded();
return memSize;
}
/** {@inheritDoc} */
@Override
public long getAvailableVirtualMemorySize() {
refreshIfNeeded();
return vmemAvailable;
}
/** {@inheritDoc} */
@Override
public long getAvailablePhysicalMemorySize() {
refreshIfNeeded();
return memAvailable;
}
/** {@inheritDoc} */
@Override
public int getNumProcessors() {
refreshIfNeeded();
return numProcessors;
}
/** {@inheritDoc} */
@Override
public int getNumCores() {
return getNumProcessors();
}
/** {@inheritDoc} */
@Override
public long getCpuFrequency() {
refreshIfNeeded();
return cpuFrequencyKhz;
}
/** {@inheritDoc} */
@Override
public long getCumulativeCpuTime() {
refreshIfNeeded();
return cumulativeCpuTimeMs;
}
/** {@inheritDoc} */
@Override
public float getCpuUsagePercentage() {
refreshIfNeeded();
float ret = cpuUsage;
if (ret != -1) {
ret = ret / numProcessors;
}
return ret;
}
/** {@inheritDoc} */
@Override
public float getNumVCoresUsed() {
refreshIfNeeded();
float ret = cpuUsage;
if (ret != -1) {
ret = ret / 100F;
}
return ret;
}
/** {@inheritDoc} */
@Override
public long getNetworkBytesRead() {
refreshIfNeeded();
return netBytesRead;
}
/** {@inheritDoc} */
@Override
public long getNetworkBytesWritten() {
refreshIfNeeded();
return netBytesWritten;
}
@Override
public long getStorageBytesRead() {
refreshIfNeeded();
return storageBytesRead;
}
@Override
public long getStorageBytesWritten() {
refreshIfNeeded();
return storageBytesWritten;
}
}