This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Huge performance bottleneck with cin.read.



I have a huge performance problem with a call to a libstdc++-v3 
function. istream::read. This is true only for I/O done with cin
(by the way this is a regression with respect to g++-2.95.2 for two 
reasons, see below)

#include <iostream>
#include <fstream>
#include <stdio.h>

int
main(int argc,char *argv[])
{
    const unsigned data_size = 1367160;
    char data[data_size];

    std::ifstream ifs(argv[1]);

    std::cerr << "Before ifstream::read: " << time(0) << std::endl;
    ifs.read(data,data_size);
    std::cerr << "After ifstream::read: " << time(0) << std::endl;

    std::cerr << "Before cin.read: " << time(0) << std::endl;
    std::cin.read(data,data_size);
    std::cerr << "After cin.read: " << time(0) << std::endl;

    std::cerr << "Before fread: " << time(0) << std::endl;
    fread(data,1,data_size,stdin);
    std::cerr << "After fread: " << time(0) << std::endl;
}

On my linux redhat 6.2 x86 (P III) machine, for a file toto, I get:

mururoa->ls -l toto
-rw-r--r--   1 papadop  robotvis  1367160 Mar  7 11:38 toto
mururoa->cat toto toto | ./a.out ~/Robotvis++/Libs/Image/tests/images/scully.float.inr
Before ifstream::read: 983970673
After ifstream::read: 983970673
Before cin.read: 983970673
After cin.read: 983970682
Before fread: 983970682
After fread: 983970682

With g++-2.95.2, I get:

mururoa->/usr/local/bin/g++ -g -pg -ftemplate-depth-30 -fPIC -DPIC Test.C  
Test.C: In function `int main(int, char **)':
Test.C:13: implicit declaration of function `int time(...)'

[This is a first regression, the new g++ is more lax ]

mururoa->man time [ Added #include <time.h> and recompiled.]

mururoa->/usr/local/bin/g++ -g -pg -ftemplate-depth-30 -fPIC -DPIC Test.C
mururoa->cat toto toto | ./a.out ~/Robotvis++/Libs/Image/tests/images/scully.float.inr
Before ifstream::read: 983978303
After ifstream::read: 983978303
Before cin.read: 983978303
After cin.read: 983978303
Before fread: 983978303
After fread: 983978303

[Second regression 2.95.2 was cin.read(ing) as that as the other ways 
of reading]

The crux of the problem seem to be (in fstream.tcc).

	  // XXX So that istream::getc() will only need to get 1 char,
	  // as opposed to BUF_SIZE.
	  if (__fd == 0)
	    _M_buf_size = 1;

Consequently, characters are read one by one which is extremely 
costly.

Is this absolutely necessary (I cannot find support for this in the 
standard, but my reading has been quick)???

If yes, how can we avoid this behaviour for the read function: 

One solution would be to temporarily set the buffer with a setbuf call,
but then how to set it back to its original value ?

Another would be to just change the size of the buffer temporarily 
since the allocated buffer is of optimal size (ie just _M_size is set 
to 1).

other ideas ?

My proposal is to remove the above lines (currently trying it).

	Theo.

 --------------------------------------------------------------------
 Theodore Papadopoulo
 Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
 --------------------------------------------------------------------



PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]