]> granicus.if.org Git - python/commitdiff
Merged revisions 73145 via svnmerge from
authorGregory P. Smith <greg@mad-scientist.com>
Sat, 15 Aug 2009 06:40:49 +0000 (06:40 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Sat, 15 Aug 2009 06:40:49 +0000 (06:40 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r73145 | kristjan.jonsson | 2009-06-02 06:14:08 -0700 (Tue, 02 Jun 2009) | 2 lines

  http://bugs.python.org/issue6117
  Fix O(n**2) performance problem in socket._fileobject
........

Lib/socket.py
Misc/NEWS

index d2988ae406c6bbfb533b59876660f6f4a8f88cc1..596e30cc4dc56fc9694e463b35b8a0a8ccef279d 100644 (file)
@@ -229,7 +229,7 @@ class _fileobject(object):
 
     __slots__ = ["mode", "bufsize", "softspace",
                  # "closed" is a property, see below
-                 "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf",
+                 "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf", "_wbuf_len",
                  "_close"]
 
     def __init__(self, sock, mode='rb', bufsize=-1, close=False):
@@ -255,6 +255,7 @@ class _fileobject(object):
         # realloc()ed down much smaller than their original allocation.
         self._rbuf = StringIO()
         self._wbuf = [] # A list of strings
+        self._wbuf_len = 0
         self._close = close
 
     def _getclosed(self):
@@ -281,6 +282,7 @@ class _fileobject(object):
         if self._wbuf:
             buffer = "".join(self._wbuf)
             self._wbuf = []
+            self._wbuf_len = 0
             self._sock.sendall(buffer)
 
     def fileno(self):
@@ -291,24 +293,24 @@ class _fileobject(object):
         if not data:
             return
         self._wbuf.append(data)
+        self._wbuf_len += len(data)
         if (self._wbufsize == 0 or
             self._wbufsize == 1 and '\n' in data or
-            self._get_wbuf_len() >= self._wbufsize):
+            self._wbuf_len >= self._wbufsize):
             self.flush()
 
     def writelines(self, list):
         # XXX We could do better here for very long lists
         # XXX Should really reject non-string non-buffers
-        self._wbuf.extend(filter(None, map(str, list)))
+        lines = filter(None, map(str, list))
+        self._wbuf_len += sum(map(len, lines))
+        self._wbuf.extend(lines)
         if (self._wbufsize <= 1 or
-            self._get_wbuf_len() >= self._wbufsize):
+            self._wbuf_len >= self._wbufsize):
             self.flush()
 
     def _get_wbuf_len(self):
-        buf_len = 0
-        for x in self._wbuf:
-            buf_len += len(x)
-        return buf_len
+        return self._wbuf_len
 
     def read(self, size=-1):
         # Use max, disallow tiny reads in a loop as they are very inefficient.
index 20692a07902308accb1a03db2ec4ee7898906102..8b0f7ab8b0c1f735433e88531656c01d5290353b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -70,6 +70,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #6117: Fix O(n**2) performance degradation when outputting lots of
+  small data on a buffered socket.socket.makefile() object.
+
 - Issue #6637: defaultdict.copy() did not work when the default factory
   was left unspecified.  Also, the eval/repr round-trip would fail when
   the default_factory was None.