Commit 7039364
authored
avoid per-frame cleanup closures on read to remove 2 allocs per frame read (#565)
read: avoid per-frame cleanup closures
Every frame header and payload read called prepareRead, which returned a
cleanup function to clear the timeout and translate close or cancellation
errors. That function captured the context, connection, and the address of
the caller's named error result. Because prepareRead returned the function,
the closure outlived its stack frame and Go allocated its captured state on
the heap for every frame read.
Move the cleanup logic to a normal finishRead method and defer a direct
method call instead. This preserves timeout cleanup and error translation
without returning a closure. Compiler escape analysis with -gcflags=-m=2
confirms that the old function literal escaped and forced the named error
result in readFrameHeader and readFramePayload onto the heap; neither escape
remains after this change.
The results below compare parent d099e16 with this commit on an Apple
M4 Max using GOMAXPROCS=1 and benchstat over 10 samples. A temporary
in-package harness, not included in this commit, repeatedly called one
internal frame read. Header reads parse a minimal frame header; payload reads
copy 512 bytes from a buffered repeating reader. The background cases use
context.Background, while the cancelable cases use an uncanceled
context.WithCancel.
Removing the escaping closure eliminates 2 allocations and 64 bytes from
every frame read: one allocation for the closure environment and one for the
named error result retained by that closure. Header reads with a background
context improve from 170.5 to 118.5 ns/op, 216 to 152 B/op, and 6 to
4 allocs/op. Header reads with a cancelable context improve from 211.1 to
158.7 ns/op with the same allocation reduction. Payload reads remove the
same fixed overhead; they remain slower because the benchmark also copies
512 bytes.
Both context types benefit because this commit does not change timeout
registration. It only removes cleanup allocations made after every
prepareRead call. An interleaved 12-sample
BenchmarkConn/disabledCompress run, which exercises complete message reads,
improves from 3.875 to 3.657 us/op (-5.63%), 42 to 32 allocs/op (-23.81%),
and 1536 to 1216 B/op (-20.83%).1 parent d099e16 commit 7039364
1 file changed
Lines changed: 26 additions & 29 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
217 | 217 | | |
218 | 218 | | |
219 | 219 | | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
| 220 | + | |
| 221 | + | |
227 | 222 | | |
228 | 223 | | |
229 | | - | |
| 224 | + | |
230 | 225 | | |
231 | 226 | | |
232 | 227 | | |
233 | 228 | | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | 229 | | |
249 | 230 | | |
250 | 231 | | |
251 | 232 | | |
252 | | - | |
253 | | - | |
| 233 | + | |
| 234 | + | |
254 | 235 | | |
255 | 236 | | |
256 | | - | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
257 | 254 | | |
258 | 255 | | |
259 | 256 | | |
260 | | - | |
| 257 | + | |
261 | 258 | | |
262 | 259 | | |
263 | 260 | | |
264 | | - | |
| 261 | + | |
265 | 262 | | |
266 | 263 | | |
267 | 264 | | |
| |||
272 | 269 | | |
273 | 270 | | |
274 | 271 | | |
275 | | - | |
| 272 | + | |
276 | 273 | | |
277 | 274 | | |
278 | 275 | | |
279 | | - | |
| 276 | + | |
280 | 277 | | |
281 | 278 | | |
282 | 279 | | |
| |||
0 commit comments