129 * In general there are 4 points where ByteBuffers are used: |
129 * In general there are 4 points where ByteBuffers are used: |
130 * - incoming/outgoing frames from/to ByteBuffers plus incoming/outgoing encrypted data |
130 * - incoming/outgoing frames from/to ByteBuffers plus incoming/outgoing encrypted data |
131 * in case of SSL connection. |
131 * in case of SSL connection. |
132 * |
132 * |
133 * 1. Outgoing frames encoded to ByteBuffers. |
133 * 1. Outgoing frames encoded to ByteBuffers. |
134 * Outgoing ByteBuffers are created with requited size and frequently small (except DataFrames, etc) |
134 * Outgoing ByteBuffers are created with required size and frequently small (except DataFrames, etc) |
135 * At this place no pools at all. All outgoing buffers should be collected by GC. |
135 * At this place no pools at all. All outgoing buffers should be collected by GC. |
136 * |
136 * |
137 * 2. Incoming ByteBuffers (decoded to frames). |
137 * 2. Incoming ByteBuffers (decoded to frames). |
138 * Here, total elimination of BB pool is not a good idea. |
138 * Here, total elimination of BB pool is not a good idea. |
139 * We don't know how many bytes we will receive through network. |
139 * We don't know how many bytes we will receive through network. |
140 * So here we allocate buffer of reasonable size. The following life of the BB: |
|
141 * - If all frames decoded from the BB are other than DataFrame and HeaderFrame (and HeaderFrame subclasses) |
|
142 * BB is returned to pool, |
|
143 * - If we decoded DataFrame from the BB. In that case DataFrame refers to subbuffer obtained by slice() method. |
|
144 * Such BB is never returned to pool and will be GCed. |
|
145 * - If we decoded HeadersFrame from the BB. Then header decoding is performed inside processFrame method and |
|
146 * the buffer could be release to pool. |
|
147 * |
140 * |
148 * 3. SLL encrypted buffers. Here another pool was introduced and all net buffers are to/from the pool, |
141 * So here is a strategy we could try to implement: |
149 * because of we can't predict size encrypted packets. |
142 * We allocate buffer of reasonable size. The following life of the BB: |
|
143 * - If all frames decoded from the BB are other than DataFrame andHeaderFrame |
|
144 * (and HeaderFrame subclasses) BB is returned to pool, |
|
145 * - If we decoded DataFrame from the BB. In that case DataFrame refers to subbuffer |
|
146 * obtained by slice() method. Such BB is never returned to pool and will be GCed. |
|
147 * - If we decoded HeadersFrame from the BB. Then header decoding is performed |
|
148 * inside processFrame method and the buffer could be release to pool. |
|
149 * |
|
150 * At this moment we do not implement this strategy. |
|
151 * Instead we only use a pool for recycling SSL encrypted buffers read from |
|
152 * the socket (see 3). |
|
153 * |
|
154 * 3. SSL encrypted buffers. Here another pool was introduced and all net buffers are to/from |
|
155 * the pool, because of we can't predict size encrypted packets. |
|
156 * |
|
157 * At the moment we only recycle encrypted buffers read from the socket, and we have |
|
158 * a pool of maximum 3 (SocketTube.MAX_BUFFERS = 3) direct buffers which are shared by |
|
159 * all connections on a given client. |
|
160 * This pool is used by all SSL connections - whether HTTP/1.1 or HTTP/2, but only |
|
161 * for SSL encrypted buffers that circulate between the SocketTube publisher and |
|
162 * the SSLFlowDelegate Reader. Limiting the pool to this particular segment allows |
|
163 * us to use direct buffer and avoid one more copy. |
|
164 * See HttpClientImpl.SSLDirectBufferSupplier, SocketTube.SSLDirectBufferSource, and |
|
165 * SSLTube.recycler. |
150 * |
166 * |
151 */ |
167 */ |
152 |
168 |
153 |
169 |
154 // A small class that allows to control frames with respect to the state of |
170 // A small class that allows to control frames with respect to the state of |