internal/socket: reuse buffers in recv/sendMsgs

Use a pool to reuse internally allocated temporary buffers, i.e. the
mmsghdrs structures and the associated iovecs and sockaddr buffers.

The temporary buffers obtained from the pool are re-allocated when their
sizes are not sufficient for the current call.
The (hopefully reasonable) assumption is that RecvMsgs and SendMsgs are
called with a somewhat uniform number of Messages/Buffers. If not, the
buffers in the pool will likely be re-allocated a few times until they
reach the size required for the "biggest" caller.

This pooling can significantly reduce the temporary allocations made in
recv/sendMsgs. While the effectiveness of this change clearly depends
on the usage pattern, pressure on the GC, etc., some improvements can
already be observed in the micro-benchmark BenchmarkUDP: the number and
size of allocations per iteration decreases significantly and there is a
small but noticable improvement in time per iteration.

```
name             old time/op    new time/op    delta
UDP/Iter-1-8       5.50µs ± 2%    5.46µs ± 2%     ~     (p=0.055 n=20+20)
UDP/Batch-1-8      5.65µs ± 3%    5.56µs ± 4%   -1.68%  (p=0.011 n=20+20)
UDP/Iter-2-8       11.0µs ± 3%    11.0µs ± 3%     ~     (p=0.645 n=20+20)
UDP/Batch-2-8      8.40µs ± 3%    8.24µs ± 5%   -1.87%  (p=0.012 n=20+20)
UDP/Iter-4-8       22.0µs ± 1%    21.9µs ± 3%     ~     (p=0.437 n=17+20)
UDP/Batch-4-8      13.3µs ± 2%    12.7µs ± 2%   -4.69%  (p=0.000 n=20+20)
UDP/Iter-8-8       44.2µs ± 3%    44.0µs ± 2%     ~     (p=0.551 n=20+20)
UDP/Batch-8-8      24.2µs ± 4%    23.1µs ± 4%   -4.65%  (p=0.000 n=20+20)
UDP/Iter-16-8      87.9µs ± 4%    88.1µs ± 3%     ~     (p=0.708 n=19+20)
UDP/Batch-16-8     45.6µs ± 4%    44.1µs ± 5%   -3.12%  (p=0.000 n=20+20)
UDP/Iter-32-8       175µs ± 4%     176µs ± 4%     ~     (p=0.087 n=20+20)
UDP/Batch-32-8     87.9µs ± 1%    84.5µs ± 6%   -3.78%  (p=0.000 n=19+19)
UDP/Iter-64-8       353µs ± 3%     352µs ± 3%     ~     (p=0.414 n=20+20)
UDP/Batch-64-8      172µs ± 4%     172µs ±11%     ~     (p=0.157 n=20+20)
UDP/Iter-128-8      705µs ± 3%     699µs ± 4%     ~     (p=0.142 n=20+20)
UDP/Batch-128-8     345µs ± 2%     343µs ± 6%     ~     (p=0.134 n=20+20)
UDP/Iter-256-8     1.41ms ± 3%    1.41ms ± 4%     ~     (p=0.758 n=20+20)
UDP/Batch-256-8     692µs ± 4%     685µs ± 4%     ~     (p=0.114 n=20+20)
UDP/Iter-512-8     2.82ms ± 2%    2.81ms ± 2%     ~     (p=0.820 n=20+20)
UDP/Batch-512-8    1.27ms ± 3%    0.75ms ± 6%  -40.62%  (p=0.000 n=20+20)

name             old alloc/op   new alloc/op   delta
UDP/Iter-1-8         408B ± 0%      424B ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-1-8        440B ± 0%      232B ± 0%  -47.27%  (p=0.000 n=20+20)
UDP/Iter-2-8         816B ± 0%      848B ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-2-8        696B ± 0%      280B ± 0%  -59.77%  (p=0.000 n=20+20)
UDP/Iter-4-8       1.63kB ± 0%    1.70kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-4-8      1.22kB ± 0%    0.38kB ± 0%  -68.42%  (p=0.000 n=20+20)
UDP/Iter-8-8       3.26kB ± 0%    3.39kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-8-8      2.26kB ± 0%    0.59kB ± 0%  -73.76%  (p=0.000 n=20+20)
UDP/Iter-16-8      6.53kB ± 0%    6.78kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-16-8     4.34kB ± 0%    1.01kB ± 0%  -76.75%  (p=0.000 n=20+20)
UDP/Iter-32-8      13.1kB ± 0%    13.6kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-32-8     8.50kB ± 0%    1.84kB ± 0%  -78.34%  (p=0.000 n=20+18)
UDP/Iter-64-8      26.1kB ± 0%    27.1kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-64-8     16.8kB ± 0%     3.5kB ± 0%  -79.16%  (p=0.000 n=20+20)
UDP/Iter-128-8     52.2kB ± 0%    54.3kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-128-8    33.5kB ± 0%     6.8kB ± 0%  -79.56%  (p=0.000 n=20+16)
UDP/Iter-256-8      104kB ± 0%     109kB ± 0%   +3.92%  (p=0.000 n=20+17)
UDP/Batch-256-8    66.7kB ± 0%    13.5kB ± 0%  -79.77%  (p=0.000 n=20+20)
UDP/Iter-512-8      209kB ± 0%     217kB ± 0%   +3.92%  (p=0.000 n=20+20)
UDP/Batch-512-8     121kB ± 0%      15kB ± 0%  -87.89%  (p=0.000 n=20+20)

name             old allocs/op  new allocs/op  delta
UDP/Iter-1-8         14.0 ± 0%      14.0 ± 0%     ~     (all equal)
UDP/Batch-1-8        14.0 ± 0%       8.0 ± 0%  -42.86%  (p=0.000 n=20+20)
UDP/Iter-2-8         28.0 ± 0%      28.0 ± 0%     ~     (all equal)
UDP/Batch-2-8        20.0 ± 0%      10.0 ± 0%  -50.00%  (p=0.000 n=20+20)
UDP/Iter-4-8         56.0 ± 0%      56.0 ± 0%     ~     (all equal)
UDP/Batch-4-8        32.0 ± 0%      14.0 ± 0%  -56.25%  (p=0.000 n=20+20)
UDP/Iter-8-8          112 ± 0%       112 ± 0%     ~     (all equal)
UDP/Batch-8-8        56.0 ± 0%      22.0 ± 0%  -60.71%  (p=0.000 n=20+20)
UDP/Iter-16-8         224 ± 0%       224 ± 0%     ~     (all equal)
UDP/Batch-16-8        104 ± 0%        38 ± 0%  -63.46%  (p=0.000 n=20+20)
UDP/Iter-32-8         448 ± 0%       448 ± 0%     ~     (all equal)
UDP/Batch-32-8        200 ± 0%        70 ± 0%  -65.00%  (p=0.000 n=20+20)
UDP/Iter-64-8         896 ± 0%       896 ± 0%     ~     (all equal)
UDP/Batch-64-8        392 ± 0%       134 ± 0%  -65.82%  (p=0.000 n=20+20)
UDP/Iter-128-8      1.79k ± 0%     1.79k ± 0%     ~     (all equal)
UDP/Batch-128-8       776 ± 0%       262 ± 0%  -66.24%  (p=0.000 n=20+20)
UDP/Iter-256-8      3.58k ± 0%     3.58k ± 0%     ~     (all equal)
UDP/Batch-256-8     1.54k ± 0%     0.52k ± 0%  -66.45%  (p=0.000 n=20+20)
UDP/Iter-512-8      7.17k ± 0%     7.17k ± 0%     ~     (all equal)
UDP/Batch-512-8     2.61k ± 0%     0.56k ± 0%  -78.48%  (p=0.000 n=20+20)
```

Fixes golang/go#26838

Change-Id: Id34e362737455cd48df5bc751426be49fbc28094
GitHub-Last-Rev: 4e33d507bb0325fd2cd8b58b586081de1acdf2ad
GitHub-Pull-Request: golang/net#102
Reviewed-on: https://go-review.googlesource.com/c/net/+/315589
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
4 files changed
tree: c2f9971046c93ba835e85d24fffdc340345aee91
  1. .gitattributes
  2. .gitignore
  3. AUTHORS
  4. CONTRIBUTING.md
  5. CONTRIBUTORS
  6. LICENSE
  7. PATENTS
  8. README.md
  9. bpf/
  10. codereview.cfg
  11. context/
  12. dict/
  13. dns/
  14. go.mod
  15. go.sum
  16. html/
  17. http/
  18. http2/
  19. icmp/
  20. idna/
  21. internal/
  22. ipv4/
  23. ipv6/
  24. lif/
  25. nettest/
  26. netutil/
  27. proxy/
  28. publicsuffix/
  29. route/
  30. trace/
  31. webdav/
  32. websocket/
  33. xsrftoken/
README.md

Go Networking

Go Reference

This repository holds supplementary Go networking libraries.

Download/Install

The easiest way to install is to run go get -u golang.org/x/net. You can also manually git clone the repository to $GOPATH/src/golang.org/x/net.

Report Issues / Send Patches

This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://golang.org/doc/contribute.html. The main issue tracker for the net repository is located at https://github.com/golang/go/issues. Prefix your issue with “x/net:” in the subject line, so it is easy to find.