This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFC] Strive to prefer sbumpc() to snextc()?!?
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Cc: Nathan Myers <ncm at cantrip dot org>
- Date: Thu, 22 Apr 2004 13:05:05 +0200
- Subject: [RFC] Strive to prefer sbumpc() to snextc()?!?
Hi,
while working on 15002 I noticed that in some istream functions we
use sbumpc(), in some, snextc(). Indeed, the latter leads often to
more straightforward fulfillment of the correctness requirements
but, on the other hand, seems definitely less efficient (indeed, is
more complex).
For instance, suppose I want to read 600000 lines, each one 200 char
long via:
while (!f.getline(buffer, sizeof(buffer)).eof()) {}
On my machine P4-2400, -O2
current mainline
----------------
0.970u 0.100s 0:01.06 100.9% 0+0k 0+0io 201pf+0w
current + (broken) patch using sbumpc()
---------------------------------------
0.600u 0.090s 0:00.69 100.0% 0+0k 0+0io 202pf+0w
The latter results are obtained via the attached **broken** patch,
which uses sbumpc() and, incorrectly, sungetc() (which may fail!).
Now, my question is: shall we actually strive to avoid snextc()??
In case you think so, I can try fixing the attached along these lines:
use sbumpc() for the main iteration, when safe (that is when there is
for sure space in the buffer), then doing final sgetc() outside the
loop thus avoiding sungetc(). The code, here for getline and possibly
elsewhere (operator>>, get?), would become rather more ugly, but, in
my opinion, typically more efficient.
On a related note, in getline(basic_string) we are *already* using
sbumpc() instead of snextc() but in a way that doesn't seem completely
correct to me: if we reach string::max_size() *before* seeing the
delimiter (or eof) the last sbumpc() char is lost... That is, exactly
what we are doing our best to avoid in getline(char*) (via the slow
snextc()) only much less evident since string::max_size() is rather
large ;) ...
Thanks for your feedback!
Paolo.
--- istream.tcc.~1.61.~ 2004-02-08 05:46:41.000000000 +0100
+++ istream.tcc 2004-04-22 12:36:51.000000000 +0200
@@ -591,27 +591,24 @@
const int_type __idelim = traits_type::to_int_type(__delim);
const int_type __eof = traits_type::eof();
__streambuf_type* __sb = this->rdbuf();
- int_type __c = __sb->sgetc();
+ int_type __c = __sb->sbumpc();
while (_M_gcount + 1 < __n
&& !traits_type::eq_int_type(__c, __eof)
&& !traits_type::eq_int_type(__c, __idelim))
{
*__s++ = traits_type::to_char_type(__c);
- __c = __sb->snextc();
+ __c = __sb->sbumpc();
++_M_gcount;
}
if (traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
+ else if (traits_type::eq_int_type(__c, __idelim))
+ ++_M_gcount;
else
{
- if (traits_type::eq_int_type(__c, __idelim))
- {
- __sb->sbumpc();
- ++_M_gcount;
- }
- else
- __err |= ios_base::failbit;
+ __sb->sungetc();
+ __err |= ios_base::failbit;
}
}
catch(...)