0

Over Easter I made a program that would take a large log file, read it in and parse it and output this to a table view with javafx. The program works and so made it into a .jar using Intellij so it could easily be used without an IDE.

However when running the program takes about 2-3 times longer when running the I/O methods in the JAR form of the program.

(.java file)3.5 seconds reading in -> (.jar file) 11.3 seconds

(.java file)0.014 seconds writing out -> (.jar file) 0.034 seconds

I have gone through reading the over older questions about this. Have tried timing the methods, making sure the latest JDK/JRE are being used.

The methods I am pretty sure are slowing down when run as a jar are:

/**
 * Method that filters a file based on a search string and a selected radio button
 *
 * @param num          index of a selected radio button
 * @param filterSearch String that is being searched for
 * @param path         Of the log file that is being filtered through
 * @return The new file that contains only the desired lines
 */
public static String filterFile(int num, String filterSearch, String path) {

    long startTime = System.currentTimeMillis();


    ArrayList<String> toOutput = new ArrayList<>();

    Scanner in = null;

    File inputFile = new File(path);
    try {
        in = new Scanner(inputFile);

        String searchString = null;

        //While the log file has a line
        while (in.hasNext()) {
            //the next line to be searched is stored in searchString
            searchString = in.nextLine();

            switch (num) {
                //if the user radio button is selected
                case 1:
                    //if the searchString contains the filter search
                    //print the whole line to the new file
                    if (searchString.contains("user=\"" + filterSearch)) {
                        //System.out.println(searchString);
                      toOutput.add(searchString);
                    }
                    break;
                case 2:
                    //if the searchString contains the filter search
                    //print the whole line to the new file
                    if (searchString.contains("srcip=\"" + filterSearch)) {
                        toOutput.add(searchString);
                    }
                    break;
            }

        }


    } catch (Exception e) {
        System.out.println("Cannot open file: ");
        System.exit(0);
    }finally {
        in.close();
    }
    long endTime = System.currentTimeMillis();
    double duration = (endTime - startTime)/1000.0;


    System.out.println("first formatedSeconds = "+ duration);
    return createFilterFile(toOutput);
}

/**
 *  Create a new file with the filtered results inside
 * @param toPrint lines from the log file that have been filtered out
 * @return Path to this new file
 */
private static String createFilterFile(ArrayList<String> toPrint){
    long startTime = System.currentTimeMillis();

    Date date = new Date();
    String fileName = "New filtered search file " + sdf.format(date) + ".log";
    PrintWriter out = null;
    try{
        FileWriter outputFile = new FileWriter(fileName, true);


        out = new PrintWriter(outputFile);

        for(String item: toPrint){
            out.println(item);
        }


    }catch(Exception e){
        e.printStackTrace();
    }finally {
        out.close();
    }
    long endTime = System.currentTimeMillis();
    double duration = (endTime - startTime)/1000.0;

    // formatedSeconds = (0.xy seconds)

    System.out.println("second formatedSeconds = "+ duration);

    return fileName;
}

Edit added finally clause to both methods, didnt change any performance tho

This code takes the large log file, searches for each line for a searched string and adds it to an array list, then create a new file. This file is significantly smaller so can be easily opened.

Any help towards improving the performance of the jar would be appreciated and as I don't have much experience with .jar files!

EDIT: Changing From a scanner to a buffered reader drastically improved performance

(.java file)1.39 seconds reading in -> (.jar file) 1.82 seconds

(.java file)0.014 seconds writing out -> (.jar file) 0.034 seconds

/**
 * Method that filters a file based on a search string and a selected radio button
 *
 * @param num          index of a selected radio button
 * @param filterSearch String that is being searched for
 * @param path         Of the log file that is being filtered through
 * @return The new file that contains only the desired lines
 */
public static String filterFile(int num, String filterSearch, String path) {

    long startTime = System.currentTimeMillis();


    ArrayList<String> toOutput = new ArrayList<>();

    BufferedReader  reader = null;

    File inputFile = new File(path);
    try {

        reader = new BufferedReader(new FileReader(inputFile));
        String searchString = null;

        //While the log file has a line
        //the next line to be searched is stored in searchString
        while ((searchString = reader.readLine())!=null) {

            switch (num) {
                //if the user radio button is selected
                case 1:
                    //if the searchString contains the filter search
                    //print the whole line to the new file
                    if (searchString.contains("user=\"" + filterSearch)) {
                      toOutput.add(searchString);
                    }
                    break;
                case 2:
                    //if the searchString contains the filter search
                    //print the whole line to the new file
                    if (searchString.contains("srcip=\"" + filterSearch)) {
                        toOutput.add(searchString);
                    }
                    break;
            }

        }

    } catch (IOException e) {
        System.out.println("Cannot open file: ");
        System.exit(0);
    }finally {

        try{
            reader.close();

        }catch (IOException ef){

        }

    }
    long endTime = System.currentTimeMillis();
    double duration = (endTime - startTime)/1000.0;


    System.out.println("first formatedSeconds = "+ duration);
    return createFilterFile(toOutput);
}

Ofcourse there is still about half a second but this is not so noticeable if anyone can explain why there is such a drastic difference between scanner and buffered reader I would be appreciative.

Should I always use buffered reader? Is buffered writer going to give a similar performance increase? Why is there still a performance difference ?

Thanks everyone :)

Joe Kerr
  • 1
  • 2
  • 2
    Sounds weird. It could be a caching thing within your IDE. Maybe invalidate any caches and restart IDE. Does it still run as fast then? Alternatively, your IDE could be set up to run the JVM with more memory than your system will when running a jar. And by the way: The way you are writing the file is not very 'best practice'. You should put the `close()` call into a `finally`. or even better, use `try-with-resources`. – user3237736 Apr 15 '18 at 12:28
  • @user3237736 I don't think it is to do with my IDE, I first noticed the difference between performance when I was running this code on my laptop, using netbeans when the code was slightly more messy, unless you mean something else ?, and thanks yes I will add a finally block :) – Joe Kerr Apr 15 '18 at 12:42
  • Hm maybe try using a `BufferedReader` instead of the `Scanner` to read the file. I have no idea why this would solve the issue, but heck, why not try it – user3237736 Apr 15 '18 at 12:46
  • Is the file written out into the current directory? When you generate the jar, that file is within it? – OneCricketeer Apr 15 '18 at 12:52
  • @user3237736 Well that made a massive difference, I changed the scanner to a buffered reader, and it went to taking 1.39 seconds in the java file and 1.82 seconds in the jar file ( I will update my question shortly) is there any reason for this you can think of. I have not used buffered reader so don't know too much about it ? – Joe Kerr Apr 15 '18 at 13:07
  • @cricket_007 the files written by the program are written to the current directory – Joe Kerr Apr 15 '18 at 13:08
  • @JoeKerr BufferedReaders can be faster than Scanners especially on larger files. For an explanation, please google. However I have no idea why the Scanner is so much slower running within JAR vs IDE, sorry – user3237736 Apr 15 '18 at 13:10
  • BufferedReader is practically the documented way to read a file https://stackoverflow.com/a/5868528/2308683 Also, answer to my second question above? In the JAR file, can you list its contents? – OneCricketeer Apr 15 '18 at 13:14
  • @cricket_007 no the file is seperate, the jar contains just the java class files that are running the methods/gui. Then a path is found to locate this log file. If I understand your question. And I guess I have never had to use anything other than scanners which is something we were taught. – Joe Kerr Apr 15 '18 at 13:21

0 Answers0