`
sgl124764903
  • 浏览: 173839 次
  • 性别: Icon_minigender_1
  • 来自: 邯郸
社区版块
存档分类
最新评论

IO性能

 
阅读更多

转自:http://topic.csdn.net/u/20080310/10/bd73f657-f100-4e41-ad55-c8389251452d.html

java总是假定只有两种文件组织形式。
第一种,基于字节流(stream of bytes)
第二种,基于字符序列(character sequences)

java 中一个字符有两个字节。所以在从文件读字符时需要转换。

提高io性能的基本原则
1,尽量避免访问磁盘
2,尽量避免访问OS
3,尽量避免方法调用
4,尽量避免单独处理字节或字符

下面通过一个计算换行数的例子来说明这些原则是如何被应用的。

1,读
import java.io.*;
   
  public class intro1 {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  FileInputStream fis =
  new FileInputStream(args[0]);
  int cnt = 0;
  int b;
  while ((b = fis.read()) != -1) {
  if (b == '\n')
  cnt++;
  }
  fis.close();
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }
这段代码中频繁调用了OS 函数,也就是FileInputStream.read
一个本地方法负责读取文件的下一个字节。

2,采用大缓存

import java.io.*;
   
 public class intro2 {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  FileInputStream fis =
  new FileInputStream(args[0]);
  BufferedInputStream bis =
  new BufferedInputStream(fis);
  int cnt = 0;
  int b;
  while ((b = bis.read()) != -1) {
  if (b == '\n')
  cnt++;
  }
  bis.close();
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
 }
BufferedInputStream.read从缓存中读取字节。减少了底层api访问。

3,直接缓存
我们不使用BufferedInputStream 而是自己直接缓存。
这样可以减少方法调用。

 import java.io.*;
   
  public class intro3 {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  FileInputStream fis =
  new FileInputStream(args[0]);
  byte buf[] = new byte[2048];
  int cnt = 0;
  int n;
  while ((n = fis.read(buf)) != -1) {
  for (int i = 0; i < n; i++) {
  if (buf[i] == '\n')
  cnt++;
  }
  }
  fis.close();
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }

对于1m的文件 执行时间分别是
 intro1 6.9
 intro2 0.9
 intro3 0.4

最慢的和最快的时间比是 17 比 1

当然这并不是说我们总是要采用第三种方式。
其实第三种方式可能产生错误,特别是在处理end-of-file事件时(要仔细处理这类事件).
并且它可读性比较差.但是作为一个方法还是应该引起我们的注意.

第二种方式可能是最普通的方式.


【缓存】
第二种和第三种方式都用到了缓存.它确实是提高IO速度的基本手段。
这很容易让我们想起一个问题。是不是缓存越大IO越快。
JAVA 的缓存默认一般是1024 或 4048 比特。
更大的缓存可能加快IO但是也就是5% 10% 左右的小幅提升。

4,整个文件读取



  import java.io.*;
   
  public class readfile {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  int len = (int)(new File(args[0]).length());
  FileInputStream fis =
  new FileInputStream(args[0]);
  byte buf[] = new byte[len];
  fis.read(buf);
  fis.close();
  int cnt = 0;
  for (int i = 0; i < len; i++) {
  if (buf[i] == '\n')
  cnt++;
  }
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }
 
这样很方便但也有很明显的不足,内存是不是比文件大。

另外一个缓存的关注点是向终端的输出。SYSTEM.OUT默认是行缓存,
也就是说缓存在遇到一个换行符的时候会将内容强行输出。

5,阻止行缓存


  import java.io.*;
   
  public class bufout {
  public static void main(String args[]) {
  FileOutputStream fdout =
  new FileOutputStream(FileDescriptor.out);
  BufferedOutputStream bos =
  new BufferedOutputStream(fdout, 1024);
  PrintStream ps =
  new PrintStream(bos, false);
   
  System.setOut(ps);
   
  final int N = 100000;
   
  for (int i = 1; i <= N; i++)
  System.out.println(i);
   
  ps.close();
  }
  }
 
这个程序输出1到100000到终端他比默认情况下快三倍。

【随机读写文本文件】

 import java.io.*;

  public class line1 {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  FileInputStream fis =
  new FileInputStream(args[0]);
  BufferedInputStream bis =
  new BufferedInputStream(fis);
  DataInputStream dis =
  new DataInputStream(bis);
  int cnt = 0;
  while (dis.readLine() != null)
  cnt++;
  dis.close();
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }

这个程序用了古老的DataInputStream.readLine来读取字符。
新一点的方法会象下面这样



 import java.io.*;

  public class line2 {
  public static void main(String args[]) {
  if (args.length != 1) {
  System.err.println("missing filename");
  System.exit(1);
  }
  try {
  FileReader fr = new FileReader(args[0]);
  BufferedReader br = new BufferedReader(fr);
  int cnt = 0;
  while (br.readLine() != null)
  cnt++;
  br.close();
  System.out.println(cnt);
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }
 
这个方法会快一些。比如6m 200,000行的文件读取第二种方式可以有20%的提升。
但即使没有提升也应该注意到一点。第一个方法会有警告,因为DataInputStream.readLine  
这个方法没有正确变换字符,所以不要用它来处理文本文件。它可以处理ASCII的字节流。

来看下面这段程序
 import java.io.*;
   
  public class conv1 {
  public static void main(String args[]) {
  try {
  FileOutputStream fos =
  new FileOutputStream("out1");
  PrintStream ps =  
  new PrintStream(fos);
  ps.println("\uffff\u4321\u1234");
  ps.close();
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }

显然他没有写我们能看懂的字符。

☆Reader/Writer IO类是基于字符的,它可以来解决这类问题。
OutputStreamWriter 是设置编码的地方。
 import java.io.*;

  public class conv2 {
  public static void main(String args[]) {
  try {
  FileOutputStream fos =
  new FileOutputStream("out2");
  OutputStreamWriter osw =
  new OutputStreamWriter(fos, "UTF8");
  PrintWriter pw =
  new PrintWriter(osw);
  pw.println("\uffff\u4321\u1234");
  pw.close();
  }
  catch (IOException e) {
  System.err.println(e);
  }
  }
  }
这段程序设置编码方式为UTF8。

分享到:
评论

相关推荐

    windows下如何查看磁盘IO性能

    查看磁盘IO性能

    关于IO性能的测试工具

    关于IO性能的测试工具——Oracle Orion 在IT领域,尤其是数据库管理和系统性能优化方面,IO(输入/输出)性能的测试与分析至关重要。它直接影响着系统的响应速度、数据处理能力和用户体验。Oracle Orion作为一款...

    虚拟化项目中的存储IO性能估算

    虚拟化项目中的存储IO性能估算

    linux下IO性能查找命令

    linux下IO性能查找命令 集

    工作经验:windows服务器下磁盘IO性能监控和分析报告

    在IT领域,尤其是在服务器管理中,对系统的性能监控至关重要,特别是磁盘I/O性能的监控。本报告聚焦于一个特定的场景,即在一台DELL R720服务器上运行Windows Server 2012时遇到的性能问题,通过监控和分析发现了...

    存储基本IO性能测试指导书.doc

    存储基本IO性能测试指导书.doc

    WMI磁盘IO性能监控.rar

    《WMI磁盘IO性能监控:深入理解与实践》 WMI(Windows Management Instrumentation,Windows管理工具)是微软提供的一种强大的系统管理框架,它允许开发者通过标准接口访问和操作Windows系统的各种管理信息,包括...

    SQL Server 2008内存及IO性能监控

    在SQL Server 2008中,内存管理和IO性能监控是数据库管理员进行系统优化和问题排查的关键环节。本文将深入探讨这两个方面的监控方法,帮助你更好地理解和管理SQL Server的资源利用。 一、内存管理 1. **内存架构**...

    Java IO 性能优化

    ### Java IO性能优化 #### 4.1 基本IO操作 在Java开发中,`java.io`包是处理输入输出操作的核心组件。虽然它旨在简化开发人员的工作流程,但初学者常常会因为不了解其内部机制而做出降低IO性能的选择。通过深入...

    生产系统主机io性能分析指南

    生产系统主机IO性能分析是确保业务稳定运行的关键环节,尤其在面对高负载和大数据量时,磁盘IO性能成为衡量系统效能的重要指标。本文将深入探讨如何在Linux环境下监测和分析主机IO性能,涵盖dd命令的基本应用、...

    服务器IO性能评估【监控命令+性能指标+iostat使用】[收集].pdf

    服务器IO性能评估 服务器IO性能评估是对服务器磁盘IO性能的监控和评估,旨在了解服务器磁盘的活动情况、资源利用率和性能瓶颈。通过对服务器磁盘IO性能的监控和评估,可以确定服务器系统的瓶颈所在,进而进行优化和...

    易语言磁盘IO性能监控

    在本主题“易语言磁盘IO性能监控”中,我们将深入探讨如何使用易语言来开发一个能够监控磁盘输入输出(I/O)性能的程序。 磁盘I/O性能是计算机系统中至关重要的部分,因为它直接影响到数据读写的速度,进而影响整个...

    详解linux下使用IOMETER测试磁盘IO性能.doc

    "Linux 下使用 IOMETER 测试磁盘 IO 性能详解" Linux 作为一个开源的操作系统,具有高度的可扩展性和灵活性,广泛应用于服务器、数据中心、云计算等领域。在 Linux 下测试磁盘 IO 性能非常重要,因为磁盘 IO 性能...

    详解linux下使用IOMETER测试磁盘IO性能.docx

    在Linux环境中,对磁盘IO性能进行测试是评估系统整体性能的重要环节,因为磁盘的读写速度直接影响到数据存取效率。IOMETER是一款强大的性能基准测试工具,它能够帮助用户测量磁盘、网络存储设备以及服务器的性能。...

    suse系统与susert系统IO性能评测研究.pdf

    ### SUSE系统与SUSERT系统IO性能评测研究 #### 一、国内外研究现状与背景 随着信息技术的快速发展,Linux操作系统因其开源性、稳定性和安全性等特点,在服务器领域得到了广泛的应用。其中,SUSE Linux Enterprise ...

    利用缓冲区提高Java应用程序的IO性能

    ### 利用缓冲区提高Java应用程序的IO性能 #### 摘要与背景介绍 Java作为一门具有跨平台特性的编程语言,在多个领域都获得了广泛的应用。随着Java应用的不断扩展,其性能问题逐渐成为人们关注的重点,尤其是输入...

    易语言WMI磁盘IO性能监控

    在“易语言WMI磁盘IO性能监控”项目中,我们主要探讨的是如何利用易语言来实现对计算机磁盘输入/输出(I/O)性能的实时监控。 WMI(Windows Management Instrumentation)是微软提供的一个系统管理框架,它允许程序...

    易语言WMI磁盘IO性能监控易语言源码.rar

    易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar ...

    Java NIO与IO性能对比分析.pdf

    本文将分析Java NIO与Java IO在性能上的对比,并尝试找出性能差异的原因,以及探讨哪种编程模型更适合高并发的应用场景。 Java IO模型是一种阻塞型I/O模型,在数据的读写过程中,如果线程在等待数据,将会一直被挂...

    io性能测试工具iometer

    **Iometer:全面解析磁盘与网络IO性能测试工具** Iometer是一款由Intel公司研发的高性能、跨平台的输入/输出(I/O)基准测试工具,主要用于评估系统在处理磁盘和网络I/O请求时的性能。它适用于各种操作系统,包括...

Global site tag (gtag.js) - Google Analytics