Mutiproccess IO is faster than Multithreaded IO

136 views Asked by At

I have a test program that does the following based on the command line options:

1) fork multiple processes and each process completely reads the same text file sequentially

2) create multiple threads and each thread completely reads the same text file sequentially

I have noticed that the multithreaded approach takes around 35 % more time than the multiprocess approach.

Why is multiprocess IO faster than mutithreaded IO ?

Machine config: 8GB RAM, 4-core,

Here is the code and test results:

using namespace std;
#include<fstream>
#include<iostream>
#include<pthread.h>
#include<errno.h>
#include<sys/wait.h>
#include <string>



void* run_thread(void * tmp)
{
    int counter=0;
    string s;
    string input_file("perf_input");
    ifstream in(input_file.c_str(), ios_base::in);
    while(getline(in, s))
    {
        counter++;
    }
    cout<<"counter "<<counter<<endl;
}

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        cout<<"Invalid number of arguments "<<endl;
        return -1;
    }


    if(argv[1][0] == 'p')
    {
        cout<<"fork process"<<endl;
        int n = atoi(argv[2]);
        cout<<" n " <<n<<endl;

        for(int i=0;i<n;i++)
        {
            int cpid = fork();

            if(cpid< 0)
            {
                cout<<"Fork failed "<<endl;
                exit(0);
            }
            else if(cpid == 0)
            {
                //child
                cout<<"Child created "<<endl;
                run_thread(NULL);
                cout<<"Child exiting "<<endl;
                exit(0);
            }
        }

        while (waitpid(-1, NULL, 0))
        {
            if (errno == ECHILD)
            {
                break;
            }
        }
    }
    else
    {
        cout<<"create thread"<<endl;
        int n = atoi(argv[2]);
        cout<<" n " <<n<<endl;

        pthread_t *tids = new pthread_t[n];
        for(int i=0;i <n; i++)
        {
            pthread_create(tids + i, NULL, run_thread, NULL);
        }

        for(int i=0;i <n; i++)
        {
            pthread_join(*(tids + i), NULL);
        }
    }
}

Time taken for multiprocess :

time ./io_test p 20

real 0m26.170s user 1m40.149s sys 0m3.360s

Time taken for multithread:

time ./io_test t 20

real 0m35.561s user 2m14.245s sys 0m4.577s

1

There are 1 answers

2
Eugen Rieck On

I suspect you test this on some modern Desktop Linux distro with default kernel IO settings - and this is, where I suspect the answer to be found.

  • Different processes have different IO contextes, so the IO for each context is strictly sequential
  • Different threads share the IO context of their parent process, so if different threads make different progress (which is unavoidable with 4 cores and 20 threads), the IO is randomized by interleaving sequential reads from different positions