From 1cfc9c0ef334a3add718a5e01d9658bdf3c9da6d Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sat, 15 Aug 2009 06:40:49 +0000 Subject: [PATCH] Merged revisions 73145 via svnmerge from 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 | 18 ++++++++++-------- Misc/NEWS | 3 +++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py index d2988ae406c..596e30cc4dc 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -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. diff --git a/Misc/NEWS b/Misc/NEWS index 20692a07902..8b0f7ab8b0c 100644 --- 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.