Java Performance Tips 1


12. I/O Streams

The best performance can be achieved by chaining the streams. The following code gives file copying using low level byte streams FileInputStream and FileOutputStream.

    FileInputStream fis = new FileInputStream("abc.txt");
    FileOutputStream fos = new FileOutputStream("def.txt");
    
    long start = System.currentTimeMillis();
    int k;
    while((k = fis.read() ) != -1)
    {
      fos.write(k); 
    }
    long end = System.currentTimeMillis();
    System.out.println("The file copy time is " + (end-start));

The above code takes around 1500 milliseconds to copy a source file of around 1.5 lakhs bytes. To increase the performance, chaining is done as in the following program.

12.1 Using Chaining (Buffering)

The FileInputStream is chained with BufferedInputStream as in the following code.

                   
    FileInputStream fis = new FileInputStream("abc.txt");            
    BufferedInputStream bis = new BufferedInputStream(fis);      

    FileOutputStream fos = new FileOutputStream("def.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    
    long start = System.currentTimeMillis();
    int k;
    while( ( k = bis.read() ) != -1 )
    {
      bos.write(k);
    }
    long end = System.currentTimeMillis();
    System.out.println("The file copy time is " + (end-start));

Chaining with Buffered streams increases a lot of performance and the time taken is just only 15 milliseconds compared to 1500 milliseconds of the previous code.

13. Formatting

We have seen reading data and how to increase the performance. Now, we will see the performance costs of converting data into different formats. Formatting costs relate to arranging characters in desired style and writing the formats to disk storage.

Different formats are used, in the following program where the same number is squared.

import java.text.*;
public class Squaring1
{
  public static void main(String args[])
  {                                             // without formatting
    Clock c1 = new Clock();
    for(int i = 0; i < 25000; i++)
    {
      String str = "Square of " + i + " is " + i * i;
    }
    c1.printTime("Without formatting");	
				              // formatting with pre-compiled code
    Object objarray[] = new Object[2];
    MessageFormat f = new MessageFormat("Square of {0, number} is {1, number}");
    c1.setZero();
    for (int i = 0; i < 25000; i++) 
    {
      objarray[0] = new Integer(i);
      objarray[1] = new Integer(i * i);
      String str1 = f.format(objarray);
    }
    c1.printTime("Formatting with pre-compiled code");
				              // formatting without pre-compilation code
    Object objarray1[] = new Object[2];
    String str2 = "Square of {0,number} is {1,number}";
    c1.setZero();
    for (int i = 0; i < 25000; i++) 
    {
      objarray1[0] = new Integer(i);
      objarray1[1] = new Integer(i * i);
      String str3 = MessageFormat.format(str2, objarray1);
    }
    c1.printTime("Formatting without pre-compilation code");
  }
}

Output screen of Squaring1.java

In fact using message format is too slower than without using format patterns. Message formats can be used for internationalization of the applications and at the same time performance overhead is thought.

14. Getting File Information(Disk access)

Always disk access is very expensive because a language has to communicate with the underlying operating system. Disk access may be required to get the file information like size, reading and writing permissions, to know a directory or a file etc. Sometimes it may be required to know the size of the file, and at the same time, assign the value to a variable in the program. If required again, we can use the same variable without accessing again.

import java.io.*;
public class FileInfo
{
  public static void main(String args[])
  {
    File f1 = new File("abc.txt");
    Clock c1 = new Clock();
    for( int i=0; i<100; i++)
    {
      long len = f1.length();
    }
    c1.printTime("Time taken to know the file length");
  }
}

The length() does not get the size of the file directly. In turn, the JVM uses a system call to get the size of the file. Such system calls are comparatively expensive. One simple way is to avoid querying the same information twice(of course, the file size not getting changed).

5 thoughts on “Java Performance Tips 1”

Leave a Comment

Your email address will not be published.