🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.unix.programmer
Article #3466

Big performance problems with C++ file I/O

#3466
From: Aaron Isotton
Date: Sat, 17 Apr 2004 22:36
124 lines
5249 bytes
Hi,

I am writing an application reading big text files (hundreds of 
megabytes) line by line. I was reading the files using std::getline and 
I noticed that it is *incredibly* slow. So I wrote three test programs, 
one using fgets(), one using std::getline() and one using 
std::ifstream::getline(). I have read the same file (200000 lines, 39MB) 
in all cases; here are the results:

Using fgets():

aisotton@zarathustra:~/test/iotest$ time ./stdio

real    0m0.222s
user    0m0.109s
sys     0m0.073s

------------

Using std::getline():

aisotton@zarathustra:~/test/iotest$ time ./streams

real    0m6.945s
user    0m5.316s
sys     0m0.074s

------------

Using std::ifstream::getline():

aisotton@zarathustra:~/test/iotest$ time ./streams2

real    0m1.002s
user    0m0.890s
sys     0m0.074s

------------

As you can see, fgets() is more than 30 times faster than 
std::getline(), and more than 4 times faster than std::ifstream::getline().

I am not 100% sure, but I more and more believe that it must be an 
inefficient stream implementation in g++; I could at least rule out a 
few points.

- It is not a buffering problem; using strace I found out that fgets() 
uses a 4096 byte buffer, and the C++ streams a 8192 byte buffer.

- It has nothing to do with optimization. The values are roughly the 
same for all optimization levels.

- g++ 2.95 performs better than 3.2, and 3.2 better than 3.3, but they 
are still slow. Here the exact versions:

aisotton@zarathustra:~/test/iotest$ g++-2.95 -v
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)

aisotton@zarathustra:~/test/iotest$ g++-3.2 -v
Reading specs from /usr/lib/gcc-lib/i386-linux/3.2.3/specs
Configured with: ../src/configure -v 
--enable-languages=c,c++,f77,objc,ada --prefix=/usr 
--mandir=/usr/share/man --infodir=/usr/share/info 
--with-gxx-include-dir=/usr/include/c++/3.2 --enable-shared 
--with-system-zlib --enable-nls --without-included-gettext 
--enable-__cxa_atexit --enable-clocale=gnu --enable-objc-gc i386-linux
Thread model: posix
gcc version 3.2.3 (Debian)

aisotton@zarathustra:~/test/iotest$ g++-3.3 -v
Reading specs from /usr/lib/gcc-lib/i486-linux/3.3.3/specs
Configured with: ../src/configure -v 
--enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr 
--mandir=/usr/share/man --infodir=/usr/share/info 
--with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared 
--with-system-zlib --enable-nls --without-included-gettext 
--enable-__cxa_atexit --enable-clocale=gnu --enable-debug 
--enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux
Thread model: posix
gcc version 3.3.3 (Debian 20040401)

And here the times for the second test:
-- 2.95 --
real    0m4.345s
user    0m4.058s
sys     0m0.067s

-- 3.2 --
real    0m5.728s
user    0m5.311s
sys     0m0.082s

-- 3.3 --
real    0m6.586s
user    0m5.298s
sys     0m0.091s

- It has nothing to do with stdio synchronisation, since we're reading 
from files. To be really sure, I tried using

std::ios_base::sync_with_stdio(false);

(yes, before the first call!) but that didn't make any difference.

- Increasing the buffer size of the stream didn't make any real 
difference either.

Almost two years ago there was a long discussion about this on

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=gidnla.uh5.ln%40ns1.irule.be&rnum=1&prev=/groups%3Fq%3Dg%252B%252B%2Bslow%2Bstd::getline%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3Dgidnla.uh5.ln%2540ns1.irule.be%26rnum%3D1

but they didn't really come to a solution.

So, my question: am I doing something wrong or is this a bug in g++?

I've uploaded a very small "test suite" demonstrating the strange 
behaviour to http://www.isotton.com/sandbox/iotest.tar.gz ; it would 
really help me if you could try it with other compilers, too. To use it 
just unpack it and type "make test". Notice that it will create a file 
of about 40MB.

Thanks for your time,
Aaron
Technical Details
Message-ID: <o4o8l1-4em.ln1@tiger.berg21.ch>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed.icl.net!newsfeed.fjserv.net!nnx.oleane.net!oleane!in2p3.fr!irazu.switch.ch!switch.ch!news.hispeed.ch!tiger.berg21.ch!news

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: fc89c,78838ebea02c7742,start
X-Google-Attributes: gidfc89c,public
X-Google-Thread: f65d0,78838ebea02c7742,start
X-Google-Attributes: gidf65d0,public
X-Google-ArrivalTime: 2004-04-17 15:46:39 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed.icl.net!newsfeed.fjserv.net!nnx.oleane.net!oleane!in2p3.fr!irazu.switch.ch!switch.ch!news.hispeed.ch!tiger.berg21.ch!news
From: Aaron Isotton <aaron@isotton.com>
Newsgroups: comp.unix.programmer,gnu.gcc
Subject: Big performance problems with C++ file I/O
Date: Sun, 18 Apr 2004 00:36:41 +0200
Organization: Cablecom Newsserver
Lines: 124
Message-ID: <o4o8l1-4em.ln1@tiger.berg21.ch>
NNTP-Posting-Host: 217-162-158-104.dclient.hispeed.ch
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: newshispeed.ch 1082241441 23443 217.162.158.104 (17 Apr 2004 22:37:21 GMT)
X-Complaints-To: news@hispeed.ch
NNTP-Posting-Date: Sat, 17 Apr 2004 22:37:21 +0000 (UTC)
User-Agent: Mozilla Thunderbird 0.5 (X11/20040306)
X-Accept-Language: en-us, en