Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > File Read Performance Issue

Reply
Thread Tools

File Read Performance Issue

 
 
Jorgen Grahn
Guest
Posts: n/a
 
      08-19-2013
On Mon, 2013-08-19, Juha Nieminen wrote:

> Unfortunately C++ streams tend to be significantly slower than the
> C equivalents in the vast majority of implementation (every single
> one I have ever used.) With small amounts of data it doesn't matter,
> but when the data amount increases, it starts to show.
>
> If you are using C++ streams, switching to (properly used) C I/O
> functions could well cut that time to 1 minute or less. (Further
> optimization will have to be done at a higher level.)


I was going to challenge that "but iostreams are slower!" idea but it
looks like that here, too. On my Linux box, a line counting loop is
about twice as fast with fgets() compared to std::getline(stream,
string&). I was expecting a 20% difference or something.

On the other hand, both are pretty fast: 100--200 nanoseconds per line.

Interestingly, the fgets() version makes twice as many read() calls.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
 
 
 
Marcel Müller
Guest
Posts: n/a
 
      08-19-2013
On 17.08.13 15.12, Jorgen Grahn wrote:
>>> The reads at program start take a long time (~2 minutes), and
>>> although I use buffers of 4096 size,

>>
>> 4096 is no buffer nowadays. The break even of modern HDDs is above 1MB.
>> So if you think, that your task is I/O bound (low CPU usage), then
>> significantly increase the buffer size.

>
> Depends on what he means by "buffers of 4096 size". If I naively use
> iostreams to read a text file line by line, it maps to reading 8191
> bytes via the kernel interface, read(2). I hope the kernel at that
> point has read /more/ than 8191 bytes into its cache.


Yes, but for reading the kernel needs to estimate the next blocks that
you are going to read. This works best for platforms where the disk
cache is located at the filesystem driver. It works less well when the
cache is part of the block device driver, because the next LBA is not
necessarily the next block of your file. And it usually works very bad
if you do seek operations.

>> If your task is CPU bound (high CPU load) then this won't help at all.

>
> Yeah. As we all know, his problem lies somewhere else. His 2 minutes
> is four hundred times slower than the 280 ms I measure on my ancient
> hardware -- no misuse of the I/O facilities can make such a radical
> difference.


Anything is possible, but where did you get the numbers?


Marcel

 
Reply With Quote
 
 
 
 
Jorgen Grahn
Guest
Posts: n/a
 
      08-20-2013
On Mon, 2013-08-19, Marcel Müller wrote:
> On 17.08.13 15.12, Jorgen Grahn wrote:
>>>> The reads at program start take a long time (~2 minutes), and
>>>> although I use buffers of 4096 size,
>>>
>>> 4096 is no buffer nowadays. The break even of modern HDDs is above 1MB.
>>> So if you think, that your task is I/O bound (low CPU usage), then
>>> significantly increase the buffer size.

>>
>> Depends on what he means by "buffers of 4096 size". If I naively use
>> iostreams to read a text file line by line, it maps to reading 8191
>> bytes via the kernel interface, read(2). I hope the kernel at that
>> point has read /more/ than 8191 bytes into its cache.

>
> Yes, but for reading the kernel needs to estimate the next blocks that
> you are going to read. This works best for platforms where the disk
> cache is located at the filesystem driver. It works less well when the
> cache is part of the block device driver, because the next LBA is not
> necessarily the next block of your file. And it usually works very bad
> if you do seek operations.
>
>>> If your task is CPU bound (high CPU load) then this won't help at all.

>>
>> Yeah. As we all know, his problem lies somewhere else. His 2 minutes
>> is four hundred times slower than the 280 ms I measure on my ancient
>> hardware -- no misuse of the I/O facilities can make such a radical
>> difference.

>
> Anything is possible, but where did you get the numbers?


280ms? Why -- do you doubt it? I simply found a file of the right size
and (in Unix) timed 'cat file >/dev/null' or 'wc -l file' or
something. The file was in cache at that point.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      08-20-2013
On Mon, 2013-08-19, Paavo Helde wrote:
> Jorgen Grahn <(E-Mail Removed)> wrote in
> news:(E-Mail Removed):
>
>> I was going to challenge that "but iostreams are slower!" idea but it
>> looks like that here, too. On my Linux box, a line counting loop is
>> about twice as fast with fgets() compared to std::getline(stream,
>> string&). I was expecting a 20% difference or something.

>
> Yes, the iostreams slowdown factor is about 2 also in my experience, also
> for other usage than std::getline(). For example, concatenating large
> strings from pieces with std::string:perator+= seems to be about twice
> faster than using std:stringstream. My guess is this is so because of
> massive virtual function calls.


Hm, they always say iostreams are designed so that you're not doing a
virtual function call per character -- that buffer thing. So that
theory seems a bit unlikely to me. But I don't have a better one.

I suspected a performance hit from locale usage, but if that's involved
switching to the plain "C" locale didn't help.

Lastly: ten years ago I could believe my C++ (libstdc++, Gnu/Linux)
wasn't optimized. But by now surely someone has tried to fix at least
this common case: reading std::cin line by line? Strange.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Melzzzzz
Guest
Posts: n/a
 
      08-20-2013
On 20 Aug 2013 08:26:47 GMT
Jorgen Grahn <(E-Mail Removed)> wrote:

> On Mon, 2013-08-19, Paavo Helde wrote:
> > Jorgen Grahn <(E-Mail Removed)> wrote in
> > news:(E-Mail Removed):
> >
> >> I was going to challenge that "but iostreams are slower!" idea but
> >> it looks like that here, too. On my Linux box, a line counting
> >> loop is about twice as fast with fgets() compared to
> >> std::getline(stream, string&). I was expecting a 20% difference or
> >> something.

> >
> > Yes, the iostreams slowdown factor is about 2 also in my
> > experience, also for other usage than std::getline(). For example,
> > concatenating large strings from pieces with
> > std::string:perator+= seems to be about twice faster than using
> > std:stringstream. My guess is this is so because of massive
> > virtual function calls.

>
> Hm, they always say iostreams are designed so that you're not doing a
> virtual function call per character -- that buffer thing. So that
> theory seems a bit unlikely to me. But I don't have a better one.
>
> I suspected a performance hit from locale usage, but if that's
> involved switching to the plain "C" locale didn't help.
>
> Lastly: ten years ago I could believe my C++ (libstdc++, Gnu/Linux)
> wasn't optimized. But by now surely someone has tried to fix at least
> this common case: reading std::cin line by line? Strange.


With g++ stdlib implementation you have to
std::ios_base::sync_with_stdio(false) in order to get good
performance.

--
Sig.


 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      08-20-2013
On Tue, 2013-08-20, Melzzzzz wrote:
> On 20 Aug 2013 08:26:47 GMT
> Jorgen Grahn <(E-Mail Removed)> wrote:
>
>> On Mon, 2013-08-19, Paavo Helde wrote:
>> > Jorgen Grahn <(E-Mail Removed)> wrote in
>> > news:(E-Mail Removed):
>> >
>> >> I was going to challenge that "but iostreams are slower!" idea but
>> >> it looks like that here, too. On my Linux box, a line counting
>> >> loop is about twice as fast with fgets() compared to
>> >> std::getline(stream, string&). I was expecting a 20% difference or
>> >> something.
>> >
>> > Yes, the iostreams slowdown factor is about 2 also in my
>> > experience, also for other usage than std::getline(). For example,
>> > concatenating large strings from pieces with
>> > std::string:perator+= seems to be about twice faster than using
>> > std:stringstream. My guess is this is so because of massive
>> > virtual function calls.

>>
>> Hm, they always say iostreams are designed so that you're not doing a
>> virtual function call per character -- that buffer thing. So that
>> theory seems a bit unlikely to me. But I don't have a better one.
>>
>> I suspected a performance hit from locale usage, but if that's
>> involved switching to the plain "C" locale didn't help.
>>
>> Lastly: ten years ago I could believe my C++ (libstdc++, Gnu/Linux)
>> wasn't optimized. But by now surely someone has tried to fix at least
>> this common case: reading std::cin line by line? Strange.

>
> With g++ stdlib implementation you have to
> std::ios_base::sync_with_stdio(false) in order to get good
> performance.


I was just about to say "of course I had that one; it's in main() in
all my programs!" ... but I might have forgotten this time. I'll
look into it tonight.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Melzzzzz
Guest
Posts: n/a
 
      08-20-2013
On Tue, 20 Aug 2013 07:13:57 -0500, Paavo Helde wrote:

> Melzzzzz <(E-Mail Removed)> wrote in news:kuv9bt$4l2$(E-Mail Removed):
>
>> With g++ stdlib implementation you have to
>> std::ios_base::sync_with_stdio(false) in order to get good performance.

>
> This would not explain the difference between std:stringstream vs
> std::string concatenation, would it?
>


No. This is for fast cin/cout operations. Eg reading file from std::cin
with getline.

--
Sig.
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      08-20-2013
On Tue, 2013-08-20, Jorgen Grahn wrote:
> On Tue, 2013-08-20, Melzzzzz wrote:
>> On 20 Aug 2013 08:26:47 GMT
>> Jorgen Grahn <(E-Mail Removed)> wrote:
>>
>>> On Mon, 2013-08-19, Paavo Helde wrote:
>>> > Jorgen Grahn <(E-Mail Removed)> wrote in
>>> > news:(E-Mail Removed):
>>> >
>>> >> I was going to challenge that "but iostreams are slower!" idea but
>>> >> it looks like that here, too. On my Linux box, a line counting
>>> >> loop is about twice as fast with fgets() compared to
>>> >> std::getline(stream, string&). I was expecting a 20% difference or
>>> >> something.
>>> >
>>> > Yes, the iostreams slowdown factor is about 2 also in my
>>> > experience, also for other usage than std::getline(). For example,
>>> > concatenating large strings from pieces with
>>> > std::string:perator+= seems to be about twice faster than using
>>> > std:stringstream. My guess is this is so because of massive
>>> > virtual function calls.
>>>
>>> Hm, they always say iostreams are designed so that you're not doing a
>>> virtual function call per character -- that buffer thing. So that
>>> theory seems a bit unlikely to me. But I don't have a better one.
>>>
>>> I suspected a performance hit from locale usage, but if that's
>>> involved switching to the plain "C" locale didn't help.
>>>
>>> Lastly: ten years ago I could believe my C++ (libstdc++, Gnu/Linux)
>>> wasn't optimized. But by now surely someone has tried to fix at least
>>> this common case: reading std::cin line by line? Strange.

>>
>> With g++ stdlib implementation you have to
>> std::ios_base::sync_with_stdio(false) in order to get good
>> performance.

>
> I was just about to say "of course I had that one; it's in main() in
> all my programs!" ... but I might have forgotten this time. I'll
> look into it tonight.


Turns out I hadn't forgotten. So, a factor 2 difference not caused by
the stdin/std::cin connection.

But when I now try omitting std::cin::sync_with_stdio(false),
I get surprising results: a slowdown by another factor 30! To
summarize the three results, for a file of 500MB and 6.7 million
lines:

0.7s - 1.2s - 34s

The 30x slowdown is even harder to find an excuse for. Ok, so it's
avoidable -- but the workaround is obscure. I think I learned about
it here rather recently.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Performance issue while reading contents of a file using java Srividya Koduri Software 0 05-04-2010 09:37 AM
File.read(fname) vs. File.read(fname,File.size(fname)) Alex Dowad Ruby 4 05-01-2010 08:20 AM
file.read() doesn't read the whole file Sreejith K Python 24 03-24-2009 12:20 PM
read/parse flat file / performance / boost::tokenizer Knackeback C++ 5 05-11-2004 08:46 PM
Web Form Performance Versus Single File Performance jm ASP .Net 1 12-12-2003 11:14 PM



Advertisments