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]
Other format: [Raw text]

[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(...)

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