We use a single throttle for both request and response. This is
sufficient for all of our current needs.
This breaks API compatibility with previous custom dispatchers.
Dispatchers that override peekSocketPolicy() must now override
peek() instead.
The HTTP client and SPDY code are now a single module that
mockwebserver depends upon.
The tests are now in a separate module that depends on both
OkHttp and mockwebserver.
This means OkBuffer implements these interfaces directly.
That's much simpler for code that sometimes wants to access
an in-memory OkBuffer and sometimes wants to access an
I/O backed stream like a socket.
Sample output:
OkHttp [gzip, chunked, HTTP_11]
bodyByteCount=1048576 headerCount=20 threadCount=10
Requests per second: 121.0
Requests per second: 304.6
Requests per second: 379.1
Requests per second: 386.9
Requests per second: 369.2
Requests per second: 390.8
Requests per second: 368.8
Requests per second: 325.2
Requests per second: 409.4
Requests per second: 389.1
I'm unhappy with java.io:
* No timeouts.
* Every layer needs to copy bytes around. Always copying bytes.
* Features like mark/reset and available() are clumsy.
* Its awkard in mixed text/binary protocols like HTTP because
character decoding is separate and takes over the stream.
Unfortunately java.nio isn't better, just different:
* It's complex.
* Buffers are fixed size.
* No built-in buffer pooling.
* Features like mark/reset/position are clumsy.
This is an obnoxious attempt at a 3rd I/O interface, mostly
inspired by InputStream and OutputStream, but using growable
buffers instead of byte arrays as the core data container.
Sometimes we name a thread both via its ExecutorService
and via a NamedRunnable. The ExecutorService thread needs
to be named because threads are cached and will be visible
in a thread dump even when no runnables are running.
NamedRunnables are also used because they provide additional
context: the host or URL being serviced by a thread.