diff --git a/tornado/iostream.py b/tornado/iostream.py
index bcf44414..fc419dcf 100644
--- a/tornado/iostream.py
+++ b/tornado/iostream.py
@@ -82,6 +82,8 @@ _ERRNO_INPROGRESS = (errno.EINPROGRESS,)
 if hasattr(errno, "WSAEINPROGRESS"):
     _ERRNO_INPROGRESS += (errno.WSAEINPROGRESS,)  # type: ignore
 
+_WINDOWS = sys.platform.startswith('win')
+
 
 class StreamClosedError(IOError):
     """Exception raised by `IOStream` methods when the stream is closed.
@@ -158,11 +160,14 @@ class BaseIOStream(object):
                                    self.max_buffer_size // 2)
         self.max_write_buffer_size = max_write_buffer_size
         self.error = None
-        self._read_buffer = collections.deque()
-        self._write_buffer = collections.deque()
+        self._read_buffer = bytearray()
+        self._read_buffer_pos = 0
         self._read_buffer_size = 0
+        self._write_buffer = bytearray()
+        self._write_buffer_pos = 0
         self._write_buffer_size = 0
         self._write_buffer_frozen = False
+        self._pending_writes_while_frozen = []
         self._read_delimiter = None
         self._read_regex = None
         self._read_max_bytes = None
@@ -373,21 +378,16 @@ class BaseIOStream(object):
         .. versionchanged:: 4.0
             Now returns a `.Future` if no callback is given.
         """
-        assert isinstance(data, bytes)
         self._check_closed()
-        # We use bool(_write_buffer) as a proxy for write_buffer_size>0,
-        # so never put empty strings in the buffer.
         if data:
             if (self.max_write_buffer_size is not None and
                     self._write_buffer_size + len(data) > self.max_write_buffer_size):
                 raise StreamBufferFullError("Reached maximum write buffer size")
-            # Break up large contiguous strings before inserting them in the
-            # write buffer, so we don't have to recopy the entire thing
-            # as we slice off pieces to send to the socket.
-            WRITE_BUFFER_CHUNK_SIZE = 128 * 1024
-            for i in range(0, len(data), WRITE_BUFFER_CHUNK_SIZE):
-                self._write_buffer.append(data[i:i + WRITE_BUFFER_CHUNK_SIZE])
-            self._write_buffer_size += len(data)
+            if self._write_buffer_frozen:
+                self._pending_writes_while_frozen.append(data)
+            else:
+                self._write_buffer += data
+                self._write_buffer_size += len(data)
         if callback is not None:
             self._write_callback = stack_context.wrap(callback)
             future = None
@@ -396,7 +396,7 @@ class BaseIOStream(object):
             future.add_done_callback(lambda f: f.exception())
         if not self._connecting:
             self._handle_write()
-            if self._write_buffer:
+            if self._write_buffer_size:
                 self._add_io_state(self.io_loop.WRITE)
             self._maybe_add_error_listener()
         return future
@@ -466,6 +466,7 @@ class BaseIOStream(object):
             # if the IOStream object is kept alive by a reference cycle.
             # TODO: Clear the read buffer too; it currently breaks some tests.
             self._write_buffer = None
+            self._write_buffer_size = 0
 
     def reading(self):
         """Returns true if we are currently reading from the stream."""
@@ -473,7 +474,7 @@ class BaseIOStream(object):
 
     def writing(self):
         """Returns true if we are currently writing to the stream."""
-        return bool(self._write_buffer)
+        return self._write_buffer_size > 0
 
     def closed(self):
         """Returns true if the stream has been closed."""
@@ -743,7 +744,7 @@ class BaseIOStream(object):
             break
         if chunk is None:
             return 0
-        self._read_buffer.append(chunk)
+        self._read_buffer += chunk
         self._read_buffer_size += len(chunk)
         if self._read_buffer_size > self.max_buffer_size:
             gen_log.error("Reached maximum read buffer size")
@@ -791,30 +792,25 @@ class BaseIOStream(object):
             # since large merges are relatively expensive and get undone in
             # _consume().
             if self._read_buffer:
-                while True:
-                    loc = self._read_buffer[0].find(self._read_delimiter)
-                    if loc != -1:
-                        delimiter_len = len(self._read_delimiter)
-                        self._check_max_bytes(self._read_delimiter,
-                                              loc + delimiter_len)
-                        return loc + delimiter_len
-                    if len(self._read_buffer) == 1:
-                        break
-                    _double_prefix(self._read_buffer)
+                loc = self._read_buffer.find(self._read_delimiter,
+                                             self._read_buffer_pos)
+                if loc != -1:
+                    loc -= self._read_buffer_pos
+                    delimiter_len = len(self._read_delimiter)
+                    self._check_max_bytes(self._read_delimiter,
+                                          loc + delimiter_len)
+                    return loc + delimiter_len
                 self._check_max_bytes(self._read_delimiter,
-                                      len(self._read_buffer[0]))
+                                      self._read_buffer_size)
         elif self._read_regex is not None:
             if self._read_buffer:
-                while True:
-                    m = self._read_regex.search(self._read_buffer[0])
-                    if m is not None:
-                        self._check_max_bytes(self._read_regex, m.end())
-                        return m.end()
-                    if len(self._read_buffer) == 1:
-                        break
-                    _double_prefix(self._read_buffer)
-                self._check_max_bytes(self._read_regex,
-                                      len(self._read_buffer[0]))
+                m = self._read_regex.search(self._read_buffer,
+                                            self._read_buffer_pos)
+                if m is not None:
+                    loc = m.end() - self._read_buffer_pos
+                    self._check_max_bytes(self._read_regex, loc)
+                    return loc
+                self._check_max_bytes(self._read_regex, self._read_buffer_size)
         return None
 
     def _check_max_bytes(self, delimiter, size):
@@ -824,35 +820,55 @@ class BaseIOStream(object):
                 "delimiter %r not found within %d bytes" % (
                     delimiter, self._read_max_bytes))
 
+    def _freeze_write_buffer(self, size):
+        self._write_buffer_frozen = size
+
+    def _unfreeze_write_buffer(self):
+        self._write_buffer_frozen = False
+        self._write_buffer += b''.join(self._pending_writes_while_frozen)
+        self._write_buffer_size += sum(map(len, self._pending_writes_while_frozen))
+        self._pending_writes_while_frozen[:] = []
+
+    def _got_empty_write(self, size):
+        """
+        Called when a non-blocking write() failed writing anything.
+        Can be overridden in subclasses.
+        """
+
     def _handle_write(self):
-        while self._write_buffer:
+        while self._write_buffer_size:
+            assert self._write_buffer_size >= 0
             try:
-                if not self._write_buffer_frozen:
+                start = self._write_buffer_pos
+                if self._write_buffer_frozen:
+                    size = self._write_buffer_frozen
+                elif _WINDOWS:
                     # On windows, socket.send blows up if given a
                     # write buffer that's too large, instead of just
                     # returning the number of bytes it was able to
                     # process.  Therefore we must not call socket.send
                     # with more than 128KB at a time.
-                    _merge_prefix(self._write_buffer, 128 * 1024)
-                num_bytes = self.write_to_fd(self._write_buffer[0])
+                    size = 128 * 1024
+                else:
+                    size = self._write_buffer_size
+                num_bytes = self.write_to_fd(
+                    memoryview(self._write_buffer)[start:start + size])
                 if num_bytes == 0:
-                    # With OpenSSL, if we couldn't write the entire buffer,
-                    # the very same string object must be used on the
-                    # next call to send.  Therefore we suppress
-                    # merging the write buffer after an incomplete send.
-                    # A cleaner solution would be to set
-                    # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, but this is
-                    # not yet accessible from python
-                    # (http://bugs.python.org/issue8240)
-                    self._write_buffer_frozen = True
+                    self._got_empty_write(size)
                     break
-                self._write_buffer_frozen = False
-                _merge_prefix(self._write_buffer, num_bytes)
-                self._write_buffer.popleft()
+                self._write_buffer_pos += num_bytes
                 self._write_buffer_size -= num_bytes
+                # Amortized O(1) shrink
+                # (this heuristic is implemented natively in Python 3.4+
+                #  but is replicated here for Python 2)
+                if self._write_buffer_pos > self._write_buffer_size:
+                    del self._write_buffer[:self._write_buffer_pos]
+                    self._write_buffer_pos = 0
+                if self._write_buffer_frozen:
+                    self._unfreeze_write_buffer()
             except (socket.error, IOError, OSError) as e:
                 if e.args[0] in _ERRNO_WOULDBLOCK:
-                    self._write_buffer_frozen = True
+                    self._got_empty_write(size)
                     break
                 else:
                     if not self._is_connreset(e):
@@ -863,7 +879,7 @@ class BaseIOStream(object):
                                         self.fileno(), e)
                     self.close(exc_info=True)
                     return
-        if not self._write_buffer:
+        if not self._write_buffer_size:
             if self._write_callback:
                 callback = self._write_callback
                 self._write_callback = None
@@ -874,11 +890,23 @@ class BaseIOStream(object):
                 future.set_result(None)
 
     def _consume(self, loc):
+        # Consume loc bytes from the read buffer and return them
         if loc == 0:
             return b""
-        _merge_prefix(self._read_buffer, loc)
+        assert loc <= self._read_buffer_size
+        # Slice the bytearray buffer into bytes, without intermediate copying
+        b = (memoryview(self._read_buffer)
+                       [self._read_buffer_pos:self._read_buffer_pos + loc]
+                       ).tobytes()
+        self._read_buffer_pos += loc
         self._read_buffer_size -= loc
-        return self._read_buffer.popleft()
+        # Amortized O(1) shrink
+        # (this heuristic is implemented natively in Python 3.4+
+        #  but is replicated here for Python 2)
+        if self._read_buffer_pos > self._read_buffer_size:
+            del self._read_buffer[:self._read_buffer_pos]
+            self._read_buffer_pos = 0
+        return b
 
     def _check_closed(self):
         if self.closed():
@@ -1251,6 +1279,17 @@ class SSLIOStream(IOStream):
     def writing(self):
         return self._handshake_writing or super(SSLIOStream, self).writing()
 
+    def _got_empty_write(self, size):
+        # With OpenSSL, if we couldn't write the entire buffer,
+        # the very same string object must be used on the
+        # next call to send.  Therefore we suppress
+        # merging the write buffer after an incomplete send.
+        # A cleaner solution would be to set
+        # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, but this is
+        # not yet accessible from python
+        # (http://bugs.python.org/issue8240)
+        self._freeze_write_buffer(size)
+
     def _do_ssl_handshake(self):
         # Based on code from test_ssl.py in the python stdlib
         try:
@@ -1498,53 +1537,6 @@ class PipeIOStream(BaseIOStream):
         return chunk
 
 
-def _double_prefix(deque):
-    """Grow by doubling, but don't split the second chunk just because the
-    first one is small.
-    """
-    new_len = max(len(deque[0]) * 2,
-                  (len(deque[0]) + len(deque[1])))
-    _merge_prefix(deque, new_len)
-
-
-def _merge_prefix(deque, size):
-    """Replace the first entries in a deque of strings with a single
-    string of up to size bytes.
-
-    >>> d = collections.deque(['abc', 'de', 'fghi', 'j'])
-    >>> _merge_prefix(d, 5); print(d)
-    deque(['abcde', 'fghi', 'j'])
-
-    Strings will be split as necessary to reach the desired size.
-    >>> _merge_prefix(d, 7); print(d)
-    deque(['abcdefg', 'hi', 'j'])
-
-    >>> _merge_prefix(d, 3); print(d)
-    deque(['abc', 'defg', 'hi', 'j'])
-
-    >>> _merge_prefix(d, 100); print(d)
-    deque(['abcdefghij'])
-    """
-    if len(deque) == 1 and len(deque[0]) <= size:
-        return
-    prefix = []
-    remaining = size
-    while deque and remaining > 0:
-        chunk = deque.popleft()
-        if len(chunk) > remaining:
-            deque.appendleft(chunk[remaining:])
-            chunk = chunk[:remaining]
-        prefix.append(chunk)
-        remaining -= len(chunk)
-    # This data structure normally just contains byte strings, but
-    # the unittest gets messy if it doesn't use the default str() type,
-    # so do the merge based on the type of data that's actually present.
-    if prefix:
-        deque.appendleft(type(prefix[0])().join(prefix))
-    if not deque:
-        deque.appendleft(b"")
-
-
 def doctests():
     import doctest
     return doctest.DocTestSuite()

Suboptimal performance sending large messages
I notice that when I send large messages over a TCP IOStream I get considerably less bandwidth than my network provides (about 10% of total).  A bit of profiling shows that a large fraction of time is spent in `str.join` and `str.find`.

Below follows a tiny example to replicate this on localhost.
### Server

``` python
from tornado.tcpserver import TCPServer
from tornado.ioloop import IOLoop
from tornado import gen

import numpy as np
data = bytes(np.random.randint(0, 255, dtype='u1', size=100000000).data) # 100M

sentinel = b'--my-sentinel--'

class MyServer(TCPServer):
    @gen.coroutine
    def handle_stream(self, stream, address):
        yield stream.write(data + sentinel)

s = MyServer()
s.listen(8000)

IOLoop.current().start()
```
### Client

``` python
from tornado.tcpclient import TCPClient
from tornado.ioloop import IOLoop
from tornado import gen

sentinel = b'--my-sentinel--'

@gen.coroutine
def f(): 
    client = TCPClient()
    stream = yield client.connect('localhost', 8000,
                                  max_buffer_size=int(1e9))
    msg = yield stream.read_until(sentinel)
    print(len(msg))

if __name__ == '__main__':
    IOLoop().run_sync(f)
```
### Add a bit of network delay

This adds 10ms on to localhost, just to simulate being in a real network

```
# tc qdisc add dev lo root netem delay 10ms
```
### Remove network delay when done

```
# tc qdisc del dev lo root netem
```
### Profiler output

```
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       92    0.430    0.005    0.430    0.005 {method 'find' of 'str' objects}
       46    0.249    0.005    0.249    0.005 {method 'join' of 'str' objects}
       25    0.216    0.009    0.216    0.009 {method 'poll' of 'select.epoll' objects}
     1553    0.019    0.000    0.019    0.000 {method 'recv' of '_socket.socket' objects}
       46    0.008    0.000    0.259    0.006 iostream.py:1501(_double_prefix)
     1553    0.002    0.000    0.022    0.000 iostream.py:721(_read_to_buffer)
       22    0.002    0.000    0.715    0.032 iostream.py:585(_read_to_buffer_loop)
       47    0.001    0.000    0.251    0.005 iostream.py:1510(_merge_prefix)
     1553    0.001    0.000    0.020    0.000 iostream.py:1010(read_from_fd)
        1    0.001    0.001    0.934    0.934 ioloop.py:746(start)
       48    0.001    0.000    0.690    0.014 iostream.py:772(_find_read_pos)
     6549    0.000    0.000    0.000    0.000 {len}

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.957    0.957 <string>:1(<module>)
        1    0.000    0.000    0.957    0.957 ioloop.py:400(run_sync)
        1    0.001    0.001    0.957    0.957 ioloop.py:746(start)
       29    0.000    0.000    0.757    0.026 stack_context.py:271(null_wrapper)
       23    0.000    0.000    0.756    0.033 iostream.py:497(_handle_events)
       22    0.000    0.000    0.755    0.034 iostream.py:645(_handle_read)
       23    0.002    0.000    0.755    0.033 iostream.py:585(_read_to_buffer_loop)
       49    0.001    0.000    0.727    0.015 iostream.py:772(_find_read_pos)
       94    0.454    0.005    0.454    0.005 {method 'find' of 'str' objects}
       47    0.008    0.000    0.272    0.006 iostream.py:1501(_double_prefix)
       48    0.002    0.000    0.264    0.005 iostream.py:1510(_merge_prefix)
       47    0.261    0.006    0.261    0.006 {method 'join' of 'str' objects}
       26    0.198    0.008    0.198    0.008 {method 'poll' of 'select.epoll' objects}
     1553    0.002    0.000    0.026    0.000 iostream.py:721(_read_to_buffer)
     1553    0.001    0.000    0.023    0.000 iostream.py:1010(read_from_fd)
     1553    0.022    0.000    0.022    0.000 {method 'recv' of '_socket.socket' objects}
        5    0.000    0.000    0.001    0.000 ioloop.py:594(_run_callback)
        3    0.000    0.000    0.001    0.000 client.py:7(f)
```

diff --git a/tornado/test/iostream_test.py b/tornado/test/iostream_test.py
index 6e15136c..9680cb1c 100644
--- a/tornado/test/iostream_test.py
+++ b/tornado/test/iostream_test.py
@@ -602,6 +602,17 @@ class TestIOStreamMixin(object):
             server.close()
             client.close()
 
+    def test_write_memoryview(self):
+        server, client = self.make_iostream_pair()
+        try:
+            client.read_bytes(4, self.stop)
+            server.write(memoryview(b"hello"))
+            data = self.wait()
+            self.assertEqual(data, b"hell")
+        finally:
+            server.close()
+            client.close()
+
     def test_read_bytes_partial(self):
         server, client = self.make_iostream_pair()
         try:

pip install -e .
parse_log_pytest
pytest
futures mock monotonic trollius pytest
apt-get update apt-get install -y gcc
3.5
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
futures==2.2.0
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mock==5.2.0
monotonic==1.6
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
-e git+https://github.com/tornadoweb/tornado.git@9bdc3176741114ffeb1048bded5d77d9e4337bbd#egg=tornado
trollius==2.1.post2
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: tornado
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - futures==2.2.0
      - mock==5.2.0
      - monotonic==1.6
      - six==1.17.0
      - trollius==2.1.post2
prefix: /opt/conda/envs/tornado

tornado/test/iostream_test.py::TestIOStream::test_write_memoryview tornado/test/iostream_test.py::TestIOStreamSSL::test_write_memoryview tornado/test/iostream_test.py::TestIOStreamSSLContext::test_write_memoryview
tornado/test/iostream_test.py::TestIOStreamWebMixin::test_connection_closed tornado/test/iostream_test.py::TestIOStreamWebMixin::test_read_until_close tornado/test/iostream_test.py::TestIOStreamWebMixin::test_read_zero_bytes tornado/test/iostream_test.py::TestIOStreamWebMixin::test_write_while_connecting tornado/test/iostream_test.py::TestIOStreamWebMixin::test_future_interface tornado/test/iostream_test.py::TestIOStreamWebMixin::test_future_close_while_reading tornado/test/iostream_test.py::TestIOStreamWebMixin::test_future_read_until_close tornado/test/iostream_test.py::TestIOStreamMixin::test_streaming_callback_with_data_in_buffer tornado/test/iostream_test.py::TestIOStreamMixin::test_write_zero_bytes tornado/test/iostream_test.py::TestIOStreamMixin::test_connection_refused tornado/test/iostream_test.py::TestIOStreamMixin::test_gaierror tornado/test/iostream_test.py::TestIOStreamMixin::test_read_callback_error tornado/test/iostream_test.py::TestIOStreamMixin::test_streaming_callback tornado/test/iostream_test.py::TestIOStreamMixin::test_streaming_until_close tornado/test/iostream_test.py::TestIOStreamMixin::test_streaming_until_close_future tornado/test/iostream_test.py::TestIOStreamMixin::test_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamMixin::test_future_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamMixin::test_close_buffered_data tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_close_with_error tornado/test/iostream_test.py::TestIOStreamMixin::test_streaming_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamMixin::test_large_read_until tornado/test/iostream_test.py::TestIOStreamMixin::test_close_callback_with_pending_read tornado/test/iostream_test.py::TestIOStreamMixin::test_inline_read_error tornado/test/iostream_test.py::TestIOStreamMixin::test_async_read_error_logging tornado/test/iostream_test.py::TestIOStreamMixin::test_future_close_callback tornado/test/iostream_test.py::TestIOStreamMixin::test_write_memoryview tornado/test/iostream_test.py::TestIOStreamMixin::test_read_bytes_partial tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_max_bytes tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_regex_max_bytes tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_regex_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamMixin::test_read_until_regex_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamMixin::test_small_reads_from_large_buffer tornado/test/iostream_test.py::TestIOStreamMixin::test_small_read_untils_from_large_buffer tornado/test/iostream_test.py::TestIOStreamMixin::test_flow_control tornado/test/iostream_test.py::TestIOStream::test_read_until_max_bytes tornado/test/iostream_test.py::TestIOStream::test_read_until_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStream::test_read_until_max_bytes_inline tornado/test/iostream_test.py::TestIOStream::test_read_until_regex_max_bytes tornado/test/iostream_test.py::TestIOStream::test_read_until_regex_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStream::test_read_until_regex_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamSSL::test_inline_read_error tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_max_bytes tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_regex_max_bytes tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_regex_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_regex_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamSSL::test_streaming_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamSSL::test_write_zero_bytes tornado/test/iostream_test.py::TestIOStreamSSLContext::test_inline_read_error tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_max_bytes tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_regex_max_bytes tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_regex_max_bytes_ignores_extra tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_regex_max_bytes_inline tornado/test/iostream_test.py::TestIOStreamSSLContext::test_streaming_read_until_close_after_close tornado/test/iostream_test.py::TestIOStreamSSLContext::test_write_zero_bytes
tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_connection_closed tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_future_close_while_reading tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_future_interface tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_future_read_until_close tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_read_until_close tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_read_zero_bytes tornado/test/iostream_test.py::TestIOStreamWebHTTP::test_write_while_connecting tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_connection_closed tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_future_close_while_reading tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_future_interface tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_future_read_until_close tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_read_until_close tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_read_zero_bytes tornado/test/iostream_test.py::TestIOStreamWebHTTPS::test_write_while_connecting tornado/test/iostream_test.py::TestIOStream::test_async_read_error_logging tornado/test/iostream_test.py::TestIOStream::test_close_buffered_data tornado/test/iostream_test.py::TestIOStream::test_close_callback_with_pending_read tornado/test/iostream_test.py::TestIOStream::test_connection_refused tornado/test/iostream_test.py::TestIOStream::test_delayed_close_callback tornado/test/iostream_test.py::TestIOStream::test_flow_control tornado/test/iostream_test.py::TestIOStream::test_future_close_callback tornado/test/iostream_test.py::TestIOStream::test_future_delayed_close_callback tornado/test/iostream_test.py::TestIOStream::test_gaierror tornado/test/iostream_test.py::TestIOStream::test_inline_read_error tornado/test/iostream_test.py::TestIOStream::test_large_read_until tornado/test/iostream_test.py::TestIOStream::test_read_bytes_partial tornado/test/iostream_test.py::TestIOStream::test_read_callback_error tornado/test/iostream_test.py::TestIOStream::test_read_until_close_after_close tornado/test/iostream_test.py::TestIOStream::test_read_until_close_with_error tornado/test/iostream_test.py::TestIOStream::test_small_read_untils_from_large_buffer tornado/test/iostream_test.py::TestIOStream::test_small_reads_from_large_buffer tornado/test/iostream_test.py::TestIOStream::test_streaming_callback tornado/test/iostream_test.py::TestIOStream::test_streaming_callback_with_data_in_buffer tornado/test/iostream_test.py::TestIOStream::test_streaming_read_until_close_after_close tornado/test/iostream_test.py::TestIOStream::test_streaming_until_close tornado/test/iostream_test.py::TestIOStream::test_streaming_until_close_future tornado/test/iostream_test.py::TestIOStream::test_write_zero_bytes tornado/test/iostream_test.py::TestIOStreamSSL::test_async_read_error_logging tornado/test/iostream_test.py::TestIOStreamSSL::test_close_buffered_data tornado/test/iostream_test.py::TestIOStreamSSL::test_close_callback_with_pending_read tornado/test/iostream_test.py::TestIOStreamSSL::test_connection_refused tornado/test/iostream_test.py::TestIOStreamSSL::test_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamSSL::test_flow_control tornado/test/iostream_test.py::TestIOStreamSSL::test_future_close_callback tornado/test/iostream_test.py::TestIOStreamSSL::test_future_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamSSL::test_gaierror tornado/test/iostream_test.py::TestIOStreamSSL::test_large_read_until tornado/test/iostream_test.py::TestIOStreamSSL::test_read_bytes_partial tornado/test/iostream_test.py::TestIOStreamSSL::test_read_callback_error tornado/test/iostream_test.py::TestIOStreamSSL::test_read_until_close_with_error tornado/test/iostream_test.py::TestIOStreamSSL::test_small_read_untils_from_large_buffer tornado/test/iostream_test.py::TestIOStreamSSL::test_small_reads_from_large_buffer tornado/test/iostream_test.py::TestIOStreamSSL::test_streaming_callback tornado/test/iostream_test.py::TestIOStreamSSL::test_streaming_callback_with_data_in_buffer tornado/test/iostream_test.py::TestIOStreamSSL::test_streaming_until_close tornado/test/iostream_test.py::TestIOStreamSSL::test_streaming_until_close_future tornado/test/iostream_test.py::TestIOStreamSSLContext::test_async_read_error_logging tornado/test/iostream_test.py::TestIOStreamSSLContext::test_close_buffered_data tornado/test/iostream_test.py::TestIOStreamSSLContext::test_close_callback_with_pending_read tornado/test/iostream_test.py::TestIOStreamSSLContext::test_connection_refused tornado/test/iostream_test.py::TestIOStreamSSLContext::test_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamSSLContext::test_flow_control tornado/test/iostream_test.py::TestIOStreamSSLContext::test_future_close_callback tornado/test/iostream_test.py::TestIOStreamSSLContext::test_future_delayed_close_callback tornado/test/iostream_test.py::TestIOStreamSSLContext::test_gaierror tornado/test/iostream_test.py::TestIOStreamSSLContext::test_large_read_until tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_bytes_partial tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_callback_error tornado/test/iostream_test.py::TestIOStreamSSLContext::test_read_until_close_with_error tornado/test/iostream_test.py::TestIOStreamSSLContext::test_small_read_untils_from_large_buffer tornado/test/iostream_test.py::TestIOStreamSSLContext::test_small_reads_from_large_buffer tornado/test/iostream_test.py::TestIOStreamSSLContext::test_streaming_callback tornado/test/iostream_test.py::TestIOStreamSSLContext::test_streaming_callback_with_data_in_buffer tornado/test/iostream_test.py::TestIOStreamSSLContext::test_streaming_until_close tornado/test/iostream_test.py::TestIOStreamSSLContext::test_streaming_until_close_future tornado/test/iostream_test.py::TestIOStreamStartTLS::test_check_hostname tornado/test/iostream_test.py::TestIOStreamStartTLS::test_handshake_fail tornado/test/iostream_test.py::TestIOStreamStartTLS::test_start_tls_smtp tornado/test/iostream_test.py::WaitForHandshakeTest::test_wait_for_handshake_already_connected tornado/test/iostream_test.py::WaitForHandshakeTest::test_wait_for_handshake_already_waiting_error tornado/test/iostream_test.py::WaitForHandshakeTest::test_wait_for_handshake_callback tornado/test/iostream_test.py::WaitForHandshakeTest::test_wait_for_handshake_future tornado/test/iostream_test.py::TestPipeIOStream::test_pipe_iostream tornado/test/iostream_test.py::TestPipeIOStream::test_pipe_iostream_big_write
tornado/iostream.py
tornado/iostream.py