Veselin Valev
Veselin Valev

Reputation: 31

Why multithreading is slower on file writing in java

I am new to multithreading and today I tried to run some performance tests of multithreading vs single thread program under the same conditions. To my surprise I found that the single-threading option works slightly faster than the muiltithreaded. So what could be the reason?

I wrote a simple program with a string concatinating class that writes the result in a file. I created 5 arrays of 50000 zeroes and 5 output files, which are passed to the Appender class' constructor in the for-loop. In the multithreading option I call the appender.run() and in the single-threading option I comment out all threading-related lines and call appender.appendString() instead;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        int[][] input = {new int[50000], new int[50000], new int[50000], new int[50000], new int[50000]};

        File[] outputFiles = {new File("src\\text6.txt"), new File("src\\text7.txt"), new File("src\\text8.txt"),
                new File("src\\text9.txt"), new File("src\\text10.txt")};

        long startTime = System.currentTimeMillis();
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            Appender appender = new Appender(input[i], outputFiles[i]);
            threads[i] = new Thread(appender);
            threads[i].start();
            appender.run();
        }

        for (Thread thread : threads) {
            thread.join();
        }
        long stopTime = System.currentTimeMillis();

        System.out.println(stopTime - startTime);
    }
}

class Appender implements Runnable {

    private String result;
    private int[] input;
    private File outputFile;

    public Appender(int[] input, File outputFile) {
        this.result = "";
        this.input = input;
        this.outputFile = outputFile;
    }

    public void appendString() {
        for (int number : input) {
            this.result += String.valueOf(number);
        }

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(this.outputFile));) {
            writer.write(this.result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        appendString();
    }
}

The measured execution time in milliseconds is are for multitreading around 3600-3700 and single-threading 2800-2900. Completely opposite to what i expected, since all threads work on different arrays and write in different files.

Upvotes: 2

Views: 1064

Answers (4)

rustyx
rustyx

Reputation: 85412

Your code does no computation, it simply copies static data to a file. You are surely disk I/O-bound, not CPU-bound.

Writing multiple files at the same time is a pessimization; disk I/O is fastest in sequential mode (on HDD that minimizes head movements and on SSD writing large blocks is faster than writing small blocks).

Once you get to a point when computing the data is slower than storing the data, then you will benefit from parallelizing the computation part (not the storing part).

Upvotes: 1

Veselin Valev
Veselin Valev

Reputation: 31

Thanks to everyone for your answers! I learnt a lot from them! The problem in my code was one line of code that should not had been there. goughy000 opend my eyes that I shouldn't call appender.run() method, because the thread.start() calls it. Now multithreading time goes down to 1800-1900 ms.

Upvotes: 1

kostia
kostia

Reputation: 334

According to Oracle's The Java™ Tutorials on processes and threads here it mentions:

Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.

As arcy mentions in his answer, there are a lot factors that affect a multithreading environment execution.

Upvotes: 0

arcy
arcy

Reputation: 13123

The short answer is that multithreading does not, by itself, speed everything up. In fact, it can slow some things down; I have not analyzed your code, but you may have shown that to yourself in your example.

In order for a single-processor computer to do multithreading, it works in time 'slices'; it works for a while on one slice, then for a while on another slice, etc. Even on a single-processor machine, this has great advantage in situations such as a desktop UI, where you want the mouse cursor and the keyboard buttons to continue to respond for the user while the program also does other things at the same time.

But if your program is "compute-bound", that is, if the limiting factor on the program's speed is the speed at which the processor(s) can execute, then multi-threading isn't going to do any good on the single-processor example. The two threads cannot execute simultaneously, and so all you do by multithreading in the code is add the overhead of maintaining information about and switching between the time slices.

Multithreading can also be of great benefit where the code spends some of its time waiting for I/O. One thread can obtain input, hand that input off to another thread for processing, and then return in a loop to obtain more input. Without multithreading on a single-processor machine, the time spent waiting for I/O doesn't allow any processing to get done, where multithreading will allow computing to continue.

It gets different (and more complicated) on a multi-processor machine; you haven't mentioned your situation in regard to processors, but I hope this is enough to get you started understanding what's happening.

Upvotes: 1

Related Questions