[pypy-commit] pypy use-file-star-for-file: use rawbuf for readline inner loop

bdkearns noreply at buildbot.pypy.org
Wed Sep 17 01:30:45 CEST 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: use-file-star-for-file
Changeset: r73568:f96acbdfe57a
Date: 2014-09-16 18:09 -0400
http://bitbucket.org/pypy/pypy/changeset/f96acbdfe57a/

Log:	use rawbuf for readline inner loop

diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -504,73 +504,93 @@
         ll_file = self._ll_file
         newlinetypes = self._newlinetypes
         skipnextlf = self._skipnextlf
-        c = 0
+
         s = StringBuilder()
-        while True:
-            # XXX release gil for all of this rather than each getc
-            c_flockfile(ll_file)
-            if self._univ_newline:
-                while size < 0 or s.getlength() < size:
-                    c = c_getc_unlocked(ll_file)
+        buffersize = size if size > 0 else 100
+        remainsize = buffersize
+        raw_buf, gc_buf = rffi.alloc_buffer(remainsize)
+        try:
+            i = 0
+            c = ord('x')
+            while True:
+                # XXX release gil for all of this rather than each getc
+                c_flockfile(ll_file)
+                if self._univ_newline:
+                    while i < remainsize:
+                        c = c_getc_unlocked(ll_file)
+                        if c == EOF:
+                            break
+                        if skipnextlf:
+                            skipnextlf = False
+                            if c == ord('\n'):
+                                newlinetypes |= NEWLINE_CRLF
+                                c = c_getc_unlocked(ll_file)
+                                if c == EOF:
+                                    break
+                            else:
+                                newlinetypes |= NEWLINE_CR
+                        if c == ord('\r'):
+                            skipnextlf = True
+                            c = ord('\n')
+                        elif c == ord('\n'):
+                            newlinetypes |= NEWLINE_LF
+                        raw_buf[i] = chr(c)
+                        i += 1
+                        if c == ord('\n'):
+                            break
                     if c == EOF:
-                        break
-                    if skipnextlf:
-                        skipnextlf = False
+                        if c_ferror(ll_file) and rposix.get_errno() == errno.EINTR:
+                            c_funlockfile(ll_file)
+                            self._newlinetypes = newlinetypes
+                            self._skipnextlf = skipnextlf
+                            if self._signal_checker is not None:
+                                self._signal_checker()
+                            c_clearerr(ll_file)
+                            continue
+                        if skipnextlf:
+                            newlinetypes |= NEWLINE_CR
+                else:
+                    while i < remainsize:
+                        c = c_getc_unlocked(ll_file)
+                        if c == EOF:
+                            break
+                        raw_buf[i] = chr(c)
+                        i += 1
                         if c == ord('\n'):
-                            newlinetypes |= NEWLINE_CRLF
-                            c = c_getc_unlocked(ll_file)
-                            if c == EOF:
-                                break
-                        else:
-                            newlinetypes |= NEWLINE_CR
-                    if c == ord('\r'):
-                        skipnextlf = True
-                        c = ord('\n')
-                    elif c == ord('\n'):
-                        newlinetypes |= NEWLINE_LF
-                    s.append(chr(c))
-                    if c == ord('\n'):
-                        break
-                if c == EOF:
-                    if c_ferror(ll_file) and rposix.get_errno() == errno.EINTR:
-                        c_funlockfile(ll_file)
-                        self._newlinetypes = newlinetypes
-                        self._skipnextlf = skipnextlf
-                        if self._signal_checker is not None:
-                            self._signal_checker()
+                            break
+                c_funlockfile(ll_file)
+                self._newlinetypes = newlinetypes
+                self._skipnextlf = skipnextlf
+                if i == size:
+                    # we read everything in one call, try to avoid copy
+                    # (remainsize == size if i == size)
+                    return rffi.str_from_buffer(raw_buf, gc_buf, remainsize, size)
+                s.append_charpsize(raw_buf, i)
+                if c == ord('\n'):
+                    break
+                elif c == EOF:
+                    if c_ferror(ll_file):
+                        if rposix.get_errno() == errno.EINTR:
+                            if self._signal_checker is not None:
+                                self._signal_checker()
+                            c_clearerr(ll_file)
+                            continue
                         c_clearerr(ll_file)
-                        continue
-                    if skipnextlf:
-                        newlinetypes |= NEWLINE_CR
-            else:
-                while size < 0 or s.getlength() < size:
-                    c = c_getc_unlocked(ll_file)
-                    if c == EOF:
-                        break
-                    s.append(chr(c))
-                    if c == ord('\n'):
-                        break
-            c_funlockfile(ll_file)
-            self._newlinetypes = newlinetypes
-            self._skipnextlf = skipnextlf
-            if c == ord('\n'):
-                break
-            elif c == EOF:
-                if c_ferror(ll_file):
-                    if rposix.get_errno() == errno.EINTR:
-                        if self._signal_checker is not None:
-                            self._signal_checker()
-                        c_clearerr(ll_file)
-                        continue
+                        raise _from_errno(IOError)
                     c_clearerr(ll_file)
-                    raise _from_errno(IOError)
-                c_clearerr(ll_file)
-                if self._signal_checker is not None:
-                    self._signal_checker()
-                break
-            else:
-                assert s.getlength() == size
-                break
+                    if self._signal_checker is not None:
+                        self._signal_checker()
+                    break
+                if size > 0:
+                    assert s.getlength() == size
+                    break
+                buffersize += buffersize >> 2
+                remainsize = buffersize - s.getlength()
+                rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+                raw_buf, gc_buf = rffi.alloc_buffer(remainsize)
+                i = 0
+        finally:
+            rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
         return s.build()
 
     def readline(self, size=-1):


More information about the pypy-commit mailing list