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. bpf/
  2. context/
  3. dict/
  4. dns/
  5. html/
  6. http/
  7. http2/
  8. icmp/
  9. idna/
  10. internal/
  11. ipv4/
  12. ipv6/
  13. lif/
  14. nettest/
  15. netutil/
  16. proxy/
  17. publicsuffix/
  18. route/
  19. trace/
  20. webdav/
  21. websocket/
  22. xsrftoken/
  23. .gitattributes
  24. .gitignore
  25. AUTHORS
  26. CONTRIBUTING.md
  27. CONTRIBUTORS
  28. LICENSE
  29. PATENTS
  30. README.md
  31. codereview.cfg
  32. go.mod
  33. go.sum
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.