CPU時間即反映CPU全速工作時完成該進程所花費的時間
cpu時間計算CPU TIME = (# of CPU Clock Cycles) x Clock Period // “#” 表示消耗的CPU時鍾周期個數
= (# of CPU Clock Cycles)/(Clock Frequency)
cpu時間計算 = (#個cpu時鍾周期) X 電子脈沖時鍾周期 (類似於晶振產生的脈沖,而頻率就是單位時間產生脈沖數量 = 1/單個脈沖時鍾周期占用時間)
= (#個cpu時鍾周期) / 電子脈沖時鍾頻率
時間片-概述
舉個多線程程序的例子,說明時間片是怎樣工作的(java)
如上:
由此可見:兩個線程是交替執行的(數字的變化),從宏觀上(同時輸出)。
以下是搜的資料:
1,什么是時間片輪轉:
時間片輪轉調度是一種最古老,最簡單,最公平且使用最廣的算法是時間片調度。每個進程被分配一個時間段,稱作它的時間片,即該進程允許運行的時間。如果在 時間片結束時進程還在運行,則CPU將被剝奪並分配給另一個進程。如果進程在時間片結束前阻塞或結束,則CPU當即進行切換。調度程序所要做的就是維護一 張就緒進程列表,,當進程用完它的時間片后,它被移到隊列的末尾。
時間片輪轉調度中唯一有趣的一點是時間片的長度。從一個進程切換到另一個進程是需要一定時間的--保存和裝入寄存器值及內存映像,更新各種表格和隊列等。 假如進程切換(process switch) - 有時稱為上下文切換(context switch),需要5毫秒,再假設時間片設為20毫秒,則在 做完20毫秒有用的工作之后,CPU將花費5毫秒來進行進程切換。CPU時間的20%被浪費在了管理開銷上。
為了提高CPU效率,我們可以將時間片設為500毫秒。這時浪費的時間只有1%。但考慮在一個分時系統中,如果有十個交互用戶幾乎同時按下回車鍵,將發生 什么情況?假設所有其他進程都用足它們的時間片的話,最后一個不幸的進程不得不等待5秒鍾才獲得運行機會。多數用戶無法忍受一條簡短命令要5秒鍾才能做出 響應。同樣的問題在一台支持多道程序的個人計算機上也會發生。
結論可以歸結如下:時間片設得太短會導致過多的進程切換,降低了CPU效率;而設得太長又可能引起對短的交互請求的響應變差。將時間片設為100毫秒通常是一個比較合理的折衷。
舉個多線程程序的例子,說明時間片是怎樣工作的(java)
如上:
由此可見:兩個線程是交替執行的(數字的變化),從宏觀上(同時輸出)。
以下是搜的資料:
1,什么是時間片輪轉:
時間片輪轉調度是一種最古老,最簡單,最公平且使用最廣的算法是時間片調度。每個進程被分配一個時間段,稱作它的時間片,即該進程允許運行的時間。如果在 時間片結束時進程還在運行,則CPU將被剝奪並分配給另一個進程。如果進程在時間片結束前阻塞或結束,則CPU當即進行切換。調度程序所要做的就是維護一 張就緒進程列表,,當進程用完它的時間片后,它被移到隊列的末尾。
時間片輪轉調度中唯一有趣的一點是時間片的長度。從一個進程切換到另一個進程是需要一定時間的--保存和裝入寄存器值及內存映像,更新各種表格和隊列等。 假如進程切換(process switch) - 有時稱為上下文切換(context switch),需要5毫秒,再假設時間片設為20毫秒,則在 做完20毫秒有用的工作之后,CPU將花費5毫秒來進行進程切換。CPU時間的20%被浪費在了管理開銷上。
為了提高CPU效率,我們可以將時間片設為500毫秒。這時浪費的時間只有1%。但考慮在一個分時系統中,如果有十個交互用戶幾乎同時按下回車鍵,將發生 什么情況?假設所有其他進程都用足它們的時間片的話,最后一個不幸的進程不得不等待5秒鍾才獲得運行機會。多數用戶無法忍受一條簡短命令要5秒鍾才能做出 響應。同樣的問題在一台支持多道程序的個人計算機上也會發生。
結論可以歸結如下:時間片設得太短會導致過多的進程切換,降低了CPU效率;而設得太長又可能引起對短的交互請求的響應變差。將時間片設為100毫秒通常是一個比較合理的折衷。
CPU使用率:(Jconsole MBean java.lang.OperatingSystem.ProcessCpuTime )
如何取得jvm實例的cpu占用
本文會貼很多代碼,代碼遵循Google的java代碼格式。獲取數據篇
1、jmx連接的創建是一個比較重的操作,我們使用apache的common pool2創建連接工廠。
public class JmxConnectionFactory implements KeyedPooledObjectFactory<JmxServer, JMXConnector> { @Override public PooledObject<JMXConnector> makeObject(JmxServer server) throws Exception { JMXServiceURL serviceURL = new JMXServiceURL(String.format( "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", server.getHost(), server.getPort())); Map<String, Object> environment = Maps.newHashMap(); String username = server.getUsername(); String password = server.getPassword(); if ((username != null) && (password != null)) { String[] credentials = new String[2]; credentials[0] = username; credentials[1] = password; environment.put(JMXConnector.CREDENTIALS, credentials); } environment.put("sun.rmi.transport.proxy.connectTimeout", 1000); environment.put("sun.rmi.transport.tcp.responseTimeout", 3000); JMXConnector connect = JMXConnectorFactory.connect(serviceURL, environment); return new DefaultPooledObject<JMXConnector>(connect); } @Override public void destroyObject(JmxServer key, PooledObject<JMXConnector> object) throws Exception { object.getObject().close(); } @Override public boolean validateObject(JmxServer key, PooledObject<JMXConnector> object) { JMXConnector connector = object.getObject(); try { connector.getConnectionId(); return true; } catch (IOException exception) { // ignore } return false; } @Override public void activateObject(JmxServer key, PooledObject<JMXConnector> p) throws Exception { } @Override public void passivateObject(JmxServer key, PooledObject<JMXConnector> p) throws Exception { } }
2、從連接池中獲取JMX連接
private static GenericKeyedObjectPool<JmxServer, JMXConnector> POOL; private static AtomicInteger actives = new AtomicInteger(0); //.... try { JMXConnector connector = POOL.borrowObject(server); try { MBeanServerConnection mbsc = connector.getMBeanServerConnection(); // 在這個地方使用連接獲取JVM的監控數據 // ...... } finally { POOL.returnObject(server, connector); }
3、計算cpu占用的邏輯是:
獲取:ProcessCpuTime,Uptime,AvailableProcessors,然后結合上一次獲取到的數據得出,算式為:
Math.min(99F, (ProcessCpuTime-PreProcessCpuTime) / ((Uptime-PreUptime) * 10000F * AvailableProcessors));
方式一:通過獲取相應的Bean,然后通過Bean去獲取數據
private long prevUpTime, prevProcessCpuTime; // ...... RuntimeMXBean runtimeMBean = newPlatformMXBeanProxy(mbsc, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); OperatingSystemMXBean operatingSystemMBean = newPlatformMXBeanProxy(mbsc, OPERATING_SYSTEM_MXBEAN_NAME, com.sun.management.OperatingSystemMXBean.class); int nCPUs = operatingSystemMBean.getAvailableProcessors(); if (runtimeMBean != null && operatingSystemMBean != null) { long uptime = runtimeMBean.getUptime(); long processCpuTime = operatingSystemMBean.getProcessCpuTime(); if (prevUpTime != 0 && prevProcessCpuTime != 0) { long elapsedCpu = processCpuTime - prevProcessCpuTime; long elaspedTime = uptime - prevUpTime; float cpuUsage = Math.min(99F, elapsedCpu / (elaspedTime * 10000F * nCPUs)); prevUpTime = uptime; prevProcessCpuTime = processCpuTime; // JsonObject value = new JsonObject(); String key = "CpuUsage"; LOGGER.debug("received value '{}%' for item '{}'", cpuUsage, key); value.addProperty(MonitorConst.JSON_TAG_VALUE, cpuUsage); value.addProperty(MonitorConst.JSON_TAG_NAME, key); return value; } else { prevUpTime = uptime; prevProcessCpuTime = processCpuTime; } } // ......
方式二、通過key來直接獲取,代碼通用些,比較長,代碼參考zabbix gateway實現
// 通用獲取方法 protected String getStringValue(MBeanServerConnection mbsc, String key) throws Exception { MonitorItem item = new MonitorItem(key); if (item.getKeyId().equals("jmx")) { if (2 != item.getArgumentCount()) { throw new MonitorException( "required key format: jmx[<object name>,<attribute name>]"); } ObjectName objectName = new ObjectName(item.getArgument(1)); String attributeName = item.getArgument(2); String realAttributeName; String fieldNames = ""; int sep; // // Attribute name and composite data field names are separated by dots. On the other hand the // name may contain a dot too. In this case user needs to escape it with a backslash. Also the // backslash symbols in the name must be escaped. So a real separator is unescaped dot and // separatorIndex() is used to locate it. // sep = HelperFunctionChest.separatorIndex(attributeName); if (-1 != sep) { LOGGER.trace("'{}' contains composite data", attributeName); realAttributeName = attributeName.substring(0, sep); fieldNames = attributeName.substring(sep + 1); } else { realAttributeName = attributeName; } // unescape possible dots or backslashes that were escaped by user realAttributeName = HelperFunctionChest.unescapeUserInput(realAttributeName); LOGGER.trace("attributeName:'{}'", realAttributeName); LOGGER.trace("fieldNames:'{}'", fieldNames); return getPrimitiveAttributeValue(mbsc.getAttribute(objectName, realAttributeName), fieldNames); } else if (item.getKeyId().equals("jmx.discovery")) { if (0 != item.getArgumentCount()) { throw new MonitorException("required key format: jmx.discovery"); } JsonArray counters = new JsonArray(); for (ObjectName name : mbsc.queryNames(null, null)) { LOGGER.trace("discovered object '{}'", name); for (MBeanAttributeInfo attrInfo : mbsc.getMBeanInfo(name).getAttributes()) { LOGGER.trace("discovered attribute '{}'", attrInfo.getName()); if (!attrInfo.isReadable()) { LOGGER.trace("attribute not readable, skipping"); continue; } try { LOGGER.trace("looking for attributes of primitive types"); String descr = (attrInfo.getName().equals(attrInfo.getDescription()) ? null : attrInfo .getDescription()); findPrimitiveAttributes(counters, name, descr, attrInfo.getName(), mbsc.getAttribute(name, attrInfo.getName())); } catch (Exception e) { Object[] logInfo = {name, attrInfo.getName(), e}; LOGGER.trace("processing '{},{}' failed", logInfo); } } } JsonObject mapping = new JsonObject(); mapping.add(MonitorConst.JSON_TAG_DATA, counters); return mapping.toString(); } else { throw new MonitorException("key ID '%s' is not supported", item.getKeyId()); } } private String getPrimitiveAttributeValue(Object dataObject, String fieldNames) throws MonitorException { LOGGER .trace("drilling down with data object '{}' and field names '{}'", dataObject, fieldNames); if (null == dataObject) { throw new MonitorException("data object is null"); } if (fieldNames.equals("")) { if (isPrimitiveAttributeType(dataObject.getClass())) { return dataObject.toString(); } else { throw new MonitorException( "data object type is not primitive: %s" + dataObject.getClass()); } } if (dataObject instanceof CompositeData) { LOGGER.trace("'{}' contains composite data", dataObject); CompositeData comp = (CompositeData) dataObject; String dataObjectName; String newFieldNames = ""; int sep = HelperFunctionChest.separatorIndex(fieldNames); if (-1 != sep) { dataObjectName = fieldNames.substring(0, sep); newFieldNames = fieldNames.substring(sep + 1); } else { dataObjectName = fieldNames; } // unescape possible dots or backslashes that were escaped by user dataObjectName = HelperFunctionChest.unescapeUserInput(dataObjectName); return getPrimitiveAttributeValue(comp.get(dataObjectName), newFieldNames); } else { throw new MonitorException("unsupported data object type along the path: %s", dataObject.getClass()); } } private void findPrimitiveAttributes(JsonArray counters, ObjectName name, String descr, String attrPath, Object attribute) { LOGGER.trace("drilling down with attribute path '{}'", attrPath); if (isPrimitiveAttributeType(attribute.getClass())) { LOGGER.trace("found attribute of a primitive type: {}", attribute.getClass()); JsonObject counter = new JsonObject(); counter.addProperty("{#JMXDESC}", null == descr ? name + "," + attrPath : descr); counter.addProperty("{#JMXOBJ}", name.toString()); counter.addProperty("{#JMXATTR}", attrPath); counter.addProperty("{#JMXTYPE}", attribute.getClass().getName()); counter.addProperty("{#JMXVALUE}", attribute.toString()); counters.add(counter); } else if (attribute instanceof CompositeData) { LOGGER.trace("found attribute of a composite type: {}", attribute.getClass()); CompositeData comp = (CompositeData) attribute; for (String key : comp.getCompositeType().keySet()) { findPrimitiveAttributes(counters, name, descr, attrPath + "." + key, comp.get(key)); } } else if (attribute instanceof TabularDataSupport || attribute.getClass().isArray()) { LOGGER.trace("found attribute of a known, unsupported type: {}", attribute.getClass()); } else { LOGGER .trace("found attribute of an unknown, unsupported type: {}", attribute.getClass()); } } private boolean isPrimitiveAttributeType(Class<?> clazz) { Class<?>[] clazzez = {Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, String.class, java.math.BigDecimal.class, java.math.BigInteger.class, java.util.Date.class, ObjectName.class}; return HelperFunctionChest.arrayContains(clazzez, clazz); } // 使用示例 獲取:ProcessCpuTime,Uptime,AvailableProcessors,然后結合上一次獲取到的數據得出,算式為: String processCpuTime=getStringValue(mbsc, "jmx[\"java.lang:type=OperatingSystem\",ProcessCpuTime]") String uptime=getStringValue(mbsc, "jmx[\"java.lang:type=Runtime\",Uptime]", #1)-last("jmx[\"java.lang:type=Runtime\",Uptime]") String availableProcessors=getStringValue(mbsc, "jmx[\"java.lang:type=OperatingSystem\",AvailableProcessors]")
方式三、zabbix
1、clone一個Template JMX Generic,修改添加相應的item的配置,添加的Template JMX Consumer
<template> <template>Template JMX Consumer</template> <name>Template JMX Consumer</name> <groups> <group> <name>Templates</name> </group> </groups> <applications/> <items> <item> <name>AvailableProcessors</name> <type>16</type> <snmp_community/> <multiplier>0</multiplier> <snmp_oid/> <key>jmx["java.lang:type=OperatingSystem",AvailableProcessors]</key> <delay>60</delay> <history>7</history> <trends>365</trends> <status>0</status> <value_type>3</value_type> <allowed_hosts/> <units/> <delta>0</delta> <snmpv3_contextname/> <snmpv3_securityname/> <snmpv3_securitylevel>0</snmpv3_securitylevel> <snmpv3_authprotocol>0</snmpv3_authprotocol> <snmpv3_authpassphrase/> <snmpv3_privprotocol>0</snmpv3_privprotocol> <snmpv3_privpassphrase/> <formula>1</formula> <delay_flex/> <params/> <ipmi_sensor/> <data_type>0</data_type> <authtype>0</authtype> <username/> <password/> <publickey/> <privatekey/> <port/> <description/> <inventory_link>0</inventory_link> <applications> <application> <name>Operating System</name> </application> </applications> <valuemap/> </item> <item> <name>Cpu Usage</name> <type>15</type> <snmp_community/> <multiplier>0</multiplier> <snmp_oid/> <key>CpuUsage</key> <delay>30</delay> <history>7</history> <trends>365</trends> <status>0</status> <value_type>0</value_type> <allowed_hosts/> <units>%</units> <delta>0</delta> <snmpv3_contextname/> <snmpv3_securityname/> <snmpv3_securitylevel>0</snmpv3_securitylevel> <snmpv3_authprotocol>0</snmpv3_authprotocol> <snmpv3_authpassphrase/> <snmpv3_privprotocol>0</snmpv3_privprotocol> <snmpv3_privpassphrase/> <formula>1</formula> <delay_flex/> <params>(last("jmx[\"java.lang:type=OperatingSystem\",ProcessCpuTime]", #1)-last("jmx[\"java.lang:type=OperatingSystem\",ProcessCpuTime]", #2))/((last("jmx[\"java.lang:type=Runtime\",Uptime]", #1)-last("jmx[\"java.lang:type=Runtime\",Uptime]", #2))*10000*last("jmx[\"java.lang:type=OperatingSystem\",AvailableProcessors]", 0))</params> <ipmi_sensor/> <data_type>0</data_type> <authtype>0</authtype> <username/> <password/> <publickey/> <privatekey/> <port/> <description/> <inventory_link>0</inventory_link> <applications> <application> <name>Runtime</name> </application> </applications> <valuemap/> </item> <item> <name>ProcessCpuTime</name> <type>16</type> <snmp_community/> <multiplier>0</multiplier> <snmp_oid/> <key>jmx["java.lang:type=OperatingSystem",ProcessCpuTime]</key> <delay>60</delay> <history>7</history> <trends>365</trends> <status>0</status> <value_type>3</value_type> <allowed_hosts/> <units/> <delta>0</delta> <snmpv3_contextname/> <snmpv3_securityname/> <snmpv3_securitylevel>0</snmpv3_securitylevel> <snmpv3_authprotocol>0</snmpv3_authprotocol> <snmpv3_authpassphrase/> <snmpv3_privprotocol>0</snmpv3_privprotocol> <snmpv3_privpassphrase/> <formula>1</formula> <delay_flex/> <params/> <ipmi_sensor/> <data_type>0</data_type> <authtype>0</authtype> <username/> <password/> <publickey/> <privatekey/> <port/> <description/> <inventory_link>0</inventory_link> <applications> <application> <name>Operating System</name> </application> </applications> <valuemap/> </item> </items> <discovery_rules/> <macros/> <templates> <template> <name>Template JMX Generic</name> </template> </templates> <screens/> </template> // 修改原來的模板 <item> <name>jvm Uptime</name> <type>15</type> <snmp_community/> <multiplier>1</multiplier> <snmp_oid/> <key>jmxUptime</key> <delay>60</delay> <history>7</history> <trends>365</trends> <status>0</status> <value_type>3</value_type> <allowed_hosts/> <units>uptime</units> <delta>0</delta> <snmpv3_contextname/> <snmpv3_securityname/> <snmpv3_securitylevel>0</snmpv3_securitylevel> <snmpv3_authprotocol>0</snmpv3_authprotocol> <snmpv3_authpassphrase/> <snmpv3_privprotocol>0</snmpv3_privprotocol> <snmpv3_privpassphrase/> <formula>0.001</formula> <delay_flex/> <params>jmx["java.lang:type=Runtime",Uptime]</params> <ipmi_sensor/> <data_type>0</data_type> <authtype>0</authtype> <username/> <password/> <publickey/> <privatekey/> <port/> <description/> <inventory_link>0</inventory_link> <applications> <application> <name>Runtime</name> </application> </applications> <valuemap/> </item> <item> <name>jvm Uptime Microsecond</name> <type>16</type> <snmp_community/> <multiplier>0</multiplier> <snmp_oid/> <key>jmx["java.lang:type=Runtime",Uptime]</key> <delay>60</delay> <history>7</history> <trends>365</trends> <status>0</status> <value_type>3</value_type> <allowed_hosts/> <units>uptime</units> <delta>0</delta> <snmpv3_contextname/> <snmpv3_securityname/> <snmpv3_securitylevel>0</snmpv3_securitylevel> <snmpv3_authprotocol>0</snmpv3_authprotocol> <snmpv3_authpassphrase/> <snmpv3_privprotocol>0</snmpv3_privprotocol> <snmpv3_privpassphrase/> <formula>1</formula> <delay_flex/> <params/> <ipmi_sensor/> <data_type>0</data_type> <authtype>0</authtype> <username/> <password/> <publickey/> <privatekey/> <port/> <description/> <inventory_link>0</inventory_link> <applications> <application> <name>Runtime</name> </application> </applications> <valuemap/> </item>
