java取得Linuxcpu,内存,磁盘实时信息

Java 代码
import java .io.BufferedReader;  
import java .io.File;  
import java .io.FileInputStream;  
import java .io.IOException;  
import java .io.InputStreamReader;  
import java .util.StringTokenizer;  
 
/** 


* 取得linux系统下的cpu、内存信息 
*  
* */ 
public final class LinuxSystemTool  
{  
   /** 
   * get memory by used info 
   *  
   * @return int[] result 
   * result.length==4;int[0]=MemTotal;int[1]=MemFree;int[2]=SwapTotal;int[3]=SwapFree; 
   * @throws IOException 
   * @throws InterruptedException 
   */ 
   public static int[] getMemInfo() throws IOException, InterruptedException  
   {  
      File file = new File("/proc/meminfo");  
      BufferedReader br = new BufferedReader(new InputStreamReader(  
      new FileInputStream(file)));  
      int[] result = new int[4];  
      String str = null;  
      StringTokenizer token = null;  
      while((str = br.readLine()) != null)  
      {  
         token = new StringTokenizer(str);  
         if(!token.hasMoreTokens())  
            continue;  
     
         str = token.nextToken();  
         if(!token.hasMoreTokens())  
            continue;  
     
         if(str.equalsIgnoreCase("MemTotal:"))  
            result[0] = Integer.parseInt(token.nextToken());  
         else if(str.equalsIgnoreCase("MemFree:"))  
            result[1] = Integer.parseInt(token.nextToken());  
         else if(str.equalsIgnoreCase("SwapTotal:"))  
            result[2] = Integer.parseInt(token.nextToken());  
         else if(str.equalsIgnoreCase("SwapFree:"))  
            result[3] = Integer.parseInt(token.nextToken());  
      }  
     
      return result;  
   }  
 
   /** 
   * get memory by used info 
   *  
   * @return float efficiency 
   * @throws IOException 
   * @throws InterruptedException 
   */ 
   public static float getCpuInfo() throws IOException, InterruptedException  
   {  
      File file = new File("/proc/stat");  
      BufferedReader br = new BufferedReader(new InputStreamReader(  
      new FileInputStream(file)));  
      StringTokenizer token = new StringTokenizer(br.readLine());  
      token.nextToken();  
      int user1 = Integer.parseInt(token.nextToken());  
      int nice1 = Integer.parseInt(token.nextToken());  
      int sys1 = Integer.parseInt(token.nextToken());  
      int idle1 = Integer.parseInt(token.nextToken());  
     
      Thread.sleep(1000);  
 
      br = new BufferedReader(  
      new InputStreamReader(new FileInputStream(file)));  
      token = new StringTokenizer(br.readLine());  
      token.nextToken();  
      int user2 = Integer.parseInt(token.nextToken());  
      int nice2 = Integer.parseInt(token.nextToken());  
      int sys2 = Integer.parseInt(token.nextToken());  
      int idle2 = Integer.parseInt(token.nextToken());  
 
      return (float)((user2 + sys2 + nice2) - (user1 + sys1 + nice1)) / (float)((user2 + nice2 + sys2 + idle2) - (user1 + nice1 + sys1 + idle1));  
   }  
}  
 
/** 
* 测试类 
*  
* <p>@author javer QQ:84831612</p> 
* @date 2005 
*/ 
public class JaverTest  
{  
    public static void main(String[] args) throws Exception  
    {  
        int[] memInfo = LinuxSystemTool.getMemInfo();  
        System.out.println("MemTotal:" + memInfo[0]);  
        System.out.println("MemFree:" + memInfo[1]);  
        System.out.println("SwapTotal:" + memInfo[2]);  
        System.out.println("SwapFree:" + memInfo[3]);  
 
        System.out.println("CPU利用率:" + LinuxSystemTool.getCpuInfo());  
    }  


import java .io.BufferedReader;
import java .io.File;
import java .io.FileInputStream;
import java .io.IOException;
import java .io.InputStreamReader;
import java .util.StringTokenizer;

/**


* 取得linux系统下的cpu、内存信息
*
* */
public final class LinuxSystemTool
{
   /**
   * get memory by used info
   *
   * @return int[] result
   * result.length==4;int[0]=MemTotal;int[1]=MemFree;int[2]=SwapTotal;int[3]=SwapFree;
   * @throws IOException
   * @throws InterruptedException
   */
   public static int[] getMemInfo() throws IOException, InterruptedException
   {
      File file = new File("/proc/meminfo");
      BufferedReader br = new BufferedReader(new InputStreamReader(
      new FileInputStream(file)));
      int[] result = new int[4];
      String str = null;
      StringTokenizer token = null;
      while((str = br.readLine()) != null)
      {
         token = new StringTokenizer(str);
         if(!token.hasMoreTokens())
            continue;
  
         str = token.nextToken();
         if(!token.hasMoreTokens())
            continue;
  
         if(str.equalsIgnoreCase("MemTotal:"))
            result[0] = Integer.parseInt(token.nextToken());
         else if(str.equalsIgnoreCase("MemFree:"))
            result[1] = Integer.parseInt(token.nextToken());
         else if(str.equalsIgnoreCase("SwapTotal:"))
            result[2] = Integer.parseInt(token.nextToken());
         else if(str.equalsIgnoreCase("SwapFree:"))
            result[3] = Integer.parseInt(token.nextToken());
      }
  
      return result;
   }

   /**
   * get memory by used info
   *
   * @return float efficiency
   * @throws IOException
   * @throws InterruptedException
   */
   public static float getCpuInfo() throws IOException, InterruptedException
   {
      File file = new File("/proc/stat");
      BufferedReader br = new BufferedReader(new InputStreamReader(
      new FileInputStream(file)));
      StringTokenizer token = new StringTokenizer(br.readLine());
      token.nextToken();
      int user1 = Integer.parseInt(token.nextToken());
      int nice1 = Integer.parseInt(token.nextToken());
      int sys1 = Integer.parseInt(token.nextToken());
      int idle1 = Integer.parseInt(token.nextToken());
  
      Thread.sleep(1000);

      br = new BufferedReader(
      new InputStreamReader(new FileInputStream(file)));
      token = new StringTokenizer(br.readLine());
      token.nextToken();
      int user2 = Integer.parseInt(token.nextToken());
      int nice2 = Integer.parseInt(token.nextToken());
      int sys2 = Integer.parseInt(token.nextToken());
      int idle2 = Integer.parseInt(token.nextToken());

      return (float)((user2 + sys2 + nice2) - (user1 + sys1 + nice1)) / (float)((user2 + nice2 + sys2 + idle2) - (user1 + nice1 + sys1 + idle1));
   }
}

/**
* 测试类
*
* <p>@author javer QQ:84831612</p>
* @date 2005
*/
public class JaverTest
{
    public static void main(String[] args) throws Exception
    {
        int[] memInfo = LinuxSystemTool.getMemInfo();
        System.out.println("MemTotal:" + memInfo[0]);
        System.out.println("MemFree:" + memInfo[1]);
        System.out.println("SwapTotal:" + memInfo[2]);
        System.out.println("SwapFree:" + memInfo[3]);

        System.out.println("CPU利用率:" + LinuxSystemTool.getCpuInfo());
    }
} (http://people.ee.ethz.ch/~oetiker/webtools/mrtg/)就是一个很不错的选择。不过用mrtg就要装 sysstat、apache、snmp、perl之类的东西。而且安装也要好几个步骤,似乎比较麻烦。本来也想直接调用sar、vmstat之类的命 令,parse一下结果就算了。哪知道发现不同的版本的linux这些命令的结果也都是不一样。既然要按版本 parse它们的结果,那还不如直接去系统里面获得算了。于是研究了一下sysstat(http://freshmeat.net/projects /sysstat/)和gkrellm(http://gkrellm.net )的源代码,找到监测性能的数据所在。



1、CPU



在文件"/proc/stat"里面就包含了CPU的信息。每一个CPU的每一tick用在什么地方都在这个文件里面记着。后面的数字含义分别 是: user、nice、sys、idle、iowait。有些版本的kernel没有iowait这一项。这些数值表示从开机到现在,CPU的每tick用 在了哪里。例如:

cpu0 256279030 0 11832528 1637168262

就是cpu0从开机到现在有 256279030 tick用在了user消耗,11832528用在了sys消耗。所以如果想计算单位时间(例如1s)里面CPU的负载,那只需要计算1秒前后数值的差除 以每一秒的tick数量就可以了。gkrellm就是这样实现的:((200 * (v2 - v1) / CPU_TICKS_PER_SECOND) + 1) /2

例如,第一次读取/proc/stat,user的值是256279030;一秒以后再读一次,值是256289030,那么CPU在这一秒的 user消耗就是:((200 * (256289030 - 256279030) / CPU_TICKS_PER_SECOND) + 1) /2 = ((10000 * 200 / 1000000) + 1) / 2 = 1%了。



2、内存消耗



文件"/proc/meminfo"里面包含的就是内存的信息,还包括了swap的信息。例如:





$ cat /proc/meminfo

total:    used:    free:  shared: buffers:  cached:
Mem:  1057009664 851668992 205340672        0 67616768 367820800
Swap: 2146787328 164429824 1982357504
MemTotal:      1032236 kB
MemFree:        200528 kB
MemShared:           0 kB
……

不过从gkrellm的源代码看,有些版本没有前面那两行统计的信息,只能够根据下面的Key: Value这种各式的数据收集。



3、磁盘空间



从gkrellm的源代码看,这个是一个很复杂的数据。磁盘分区的数据有可能分布在:/proc/mounts、/proc /diskstats、 /proc/partitions等等。而且如果想要检查某几个特定的路径,还需要通过mount、df等命令的帮助。为了减少麻烦,这个数据我就直接用 statfs函数直接获得了。



int statfs(const char *path, struct statfs *buf);

这个函数只需要输入需要检查的路径名称,就可以返回这个路径所在的分区的空间使用情况:

总空间:buf.f_bsize * buf.f_blocks

空余空间:buf.f_bsize * buf.f_bavail



4、磁盘I/O



磁盘I/O的数据也同样比较复杂,有些版本看/proc/diskstats,有些版本看/proc/partitions,还有些版本至今我也不知道在那里看……不过可以看到数据的版本也像CPU那样,需要隔一段时间取值,两次取值的差就是流量。



5、网络流量



网络流量也是五花八门,不过基本上都可以在/proc/net/dev里面获得。同样也是需要两次取值取其差作为流量值。

Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论

<think>好的,用户问为什么在下载文件时设置byte数组的大小为4096。我需要先回顾一下相关的知识。 首先,用户之前询问了OkHttp3下载文件的代码,现在继续深入,可能是在学习如何优化文件下载,或者遇到了性能问题。用户可能注意到代码中的buffer数组大小设置为4096,想知道这个数值的选择原因。 接下来,我需要解释buffer的作用。缓冲区用于临时存储从输入流读取的数据,然后写入输出流。缓冲区的大小会影响读写操作的次数和效率。如果缓冲区太小,会增加I/O操作的次数,降低效率;太大则可能占用过多内存,尤其是在处理大量并发请求时。 然后,为什么选择4096这个数值呢?可能的原因有几个: 1. **历史惯例和标准**:许多系统和库默认使用4KB的缓冲区,这可能源于传统文件系统和磁盘块的大小,通常是4KB。使用这个大小可以对齐硬件操作,提高效率。 2. **内存对齐和性能优化**:现代CPU的缓存行通常为64字节,4096是64的倍数,这样内存访问更高效,减少缓存未命中的情况。 3. **平衡效率和内存使用**:4096在减少I/O操作次数和合理使用内存之间取得了平衡。比如,更大的缓冲区可能减少读取次数,但每个操作占用更多内存,可能影响多线程环境下的性能。 4. **网络数据包大小**:MTU(最大传输单元)通常是1500字节左右,4096可以容纳几个数据包,减少系统调用的次数,提高网络读取效率。 用户可能想知道是否有更好的数值,或者是否需要根据具体情况调整。应该说明这并非固定值,可以根据实际情况调整,比如大文件使用更大的缓冲区,而内存受限的环境使用较小的。同时,可以建议用户进行测试以找到最佳大小。 另外,用户可能没有明确的问题,但可能在实际应用中遇到性能瓶颈,或者想优化代码。需要确保解释清楚不同缓冲区大小的权衡,以及为什么4096是一个合理的选择,同时提供调整的建议。</think>在文件下载或流式数据传输中,设置 `byte[] buffer` 的大小为 **4096 字节(即 4KB)** 是一种常见的优化实践,其背后有以下原因: --- ### 1. **平衡内存和效率的折中** - **过小的缓冲区(如 512B)**:会增加读取/写入磁盘的次数(I/O 操作频繁),降低效率。 - **过大的缓冲区(如 1MB)**:虽然减少 I/O 次数,但会占用更多内存,尤其在处理大量并发下载时可能导致内存压力。 - **4096 字节** 是经验证后对内存占用和 I/O 效率的平衡值。 --- ### 2. **硬件和操作系统的底层优化** - **磁盘块大小**:传统文件系统的默认块大小通常为 **4KB**(例如 Linux 的 ext4),对齐块大小可提高磁盘读写效率。 - **内存页对齐**:现代 CPU 的缓存行(Cache Line)通常为 64 字节,而 4096 是 64 的整数倍,能更好地利用 CPU 缓存。 - **网络数据包**:TCP/IP 协议的最大传输单元(MTU)通常是 1500 字节左右,4096 可容纳多个网络包,减少系统调用次数。 --- ### 3. **编程语言与库的惯例** - Java 的 `BufferedInputStream` 默认缓冲区大小是 **8192 字节(8KB)**,而 OkHttp、Retrofit 等网络库常使用 **4KB** 作为流式传输的默认值。 - 这是一种广泛接受的“合理值”,开发者无需过度调优即可获得较好性能。 --- ### 4. **实际测试的验证** - 在大多数场景中,4KB 缓冲区已能接近磁盘或网络的吞吐极限,进一步增大缓冲区对性能提升不明显(边际效益递减)。 --- ### 何时需要调整缓冲区大小? | 场景 | 建议缓冲区大小 | 原因 | |---------------------|---------------------|------------------------------| | 大文件下载(如视频)| 8KB ~ 32KB | 减少 I/O 次数,提升吞吐量 | | 内存敏感环境(如嵌入式设备) | 1KB ~ 2KB | 降低内存占用 | | 高速网络(如 5G/WiFi 6) | 16KB ~ 64KB | 匹配高带宽,减少延迟 | --- ### 示例代码中的关键逻辑 ```java byte[] buffer = new byte[4096]; // 使用 4KB 缓冲区 int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } ``` --- ### 总结 - **4096 字节是经验值**,平衡了内存、I/O 效率和硬件特性。 - 实际开发中可根据场景调整,但 **无需过早优化**,除非有明确的性能瓶颈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值