-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
internal/socket: add message IO functionality
This change adds portable message IO methods of Conn, IO message and control message types, and parse methods for the types to provide those functionality to the ipv4 and ipv6 packages. With this change, the ipv4 and ipv6 packages can provide low-level (but less heap allocation and the cost of invoking system calls) API such as read and write operations for a batch of IO messages. On vanilla linux/amd64 virtual machine: BenchmarkUDP/Iter-1-2 1000000 8068 ns/op 408 B/op 14 allocs/op BenchmarkUDP/Batch-1-2 1000000 8610 ns/op 440 B/op 14 allocs/op BenchmarkUDP/Iter-2-2 500000 15390 ns/op 816 B/op 28 allocs/op BenchmarkUDP/Batch-2-2 500000 12715 ns/op 696 B/op 20 allocs/op BenchmarkUDP/Iter-4-2 200000 30763 ns/op 1632 B/op 56 allocs/op BenchmarkUDP/Batch-4-2 300000 21853 ns/op 1216 B/op 32 allocs/op BenchmarkUDP/Iter-8-2 100000 61460 ns/op 3264 B/op 112 allocs/op BenchmarkUDP/Batch-8-2 200000 39048 ns/op 2256 B/op 56 allocs/op BenchmarkUDP/Iter-16-2 50000 122408 ns/op 6528 B/op 224 allocs/op BenchmarkUDP/Batch-16-2 100000 72728 ns/op 4336 B/op 104 allocs/op BenchmarkUDP/Iter-32-2 30000 243137 ns/op 13056 B/op 448 allocs/op BenchmarkUDP/Batch-32-2 50000 141332 ns/op 8496 B/op 200 allocs/op BenchmarkUDP/Iter-64-2 20000 488125 ns/op 26112 B/op 896 allocs/op BenchmarkUDP/Batch-64-2 30000 282078 ns/op 16816 B/op 392 allocs/op BenchmarkUDP/Iter-128-2 10000 973752 ns/op 52224 B/op 1792 allocs/op BenchmarkUDP/Batch-128-2 10000 551021 ns/op 33456 B/op 776 allocs/op BenchmarkUDP/Iter-256-2 3000 1977852 ns/op 104448 B/op 3584 allocs/op BenchmarkUDP/Batch-256-2 10000 1252596 ns/op 66736 B/op 1544 allocs/op BenchmarkUDP/Iter-512-2 2000 4147495 ns/op 208896 B/op 7168 allocs/op BenchmarkUDP/Batch-512-2 3000 2175774 ns/op 121128 B/op 2612 allocs/op Change-Id: I3e08b28917b62dbea7936a86acb24e25ccaf5365 Reviewed-on: https://go-review.googlesource.com/38212 Run-TryBot: Mikio Hara <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
- Loading branch information
Showing
43 changed files
with
1,602 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris | ||
|
||
package socket | ||
|
||
func (h *cmsghdr) len() int { return int(h.Len) } | ||
func (h *cmsghdr) lvl() int { return int(h.Level) } | ||
func (h *cmsghdr) typ() int { return int(h.Type) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build darwin dragonfly freebsd netbsd openbsd | ||
|
||
package socket | ||
|
||
func (h *cmsghdr) set(l, lvl, typ int) { | ||
h.Len = uint32(l) | ||
h.Level = int32(lvl) | ||
h.Type = int32(typ) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm mips mipsle 386 | ||
// +build linux | ||
|
||
package socket | ||
|
||
func (h *cmsghdr) set(l, lvl, typ int) { | ||
h.Len = uint32(l) | ||
h.Level = int32(lvl) | ||
h.Type = int32(typ) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x | ||
// +build linux | ||
|
||
package socket | ||
|
||
func (h *cmsghdr) set(l, lvl, typ int) { | ||
h.Len = uint64(l) | ||
h.Level = int32(lvl) | ||
h.Type = int32(typ) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build amd64 | ||
// +build solaris | ||
|
||
package socket | ||
|
||
func (h *cmsghdr) set(l, lvl, typ int) { | ||
h.Len = uint32(l) | ||
h.Level = int32(lvl) | ||
h.Type = int32(typ) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris | ||
|
||
package socket | ||
|
||
type cmsghdr struct{} | ||
|
||
const sizeofCmsghdr = 0 | ||
|
||
func (h *cmsghdr) len() int { return 0 } | ||
func (h *cmsghdr) lvl() int { return 0 } | ||
func (h *cmsghdr) typ() int { return 0 } | ||
|
||
func (h *cmsghdr) set(l, lvl, typ int) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm mips mipsle 386 | ||
// +build darwin dragonfly freebsd linux netbsd openbsd | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (v *iovec) set(b []byte) { | ||
v.Base = (*byte)(unsafe.Pointer(&b[0])) | ||
v.Len = uint32(len(b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x | ||
// +build darwin dragonfly freebsd linux netbsd openbsd | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (v *iovec) set(b []byte) { | ||
v.Base = (*byte)(unsafe.Pointer(&b[0])) | ||
v.Len = uint64(len(b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build amd64 | ||
// +build solaris | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (v *iovec) set(b []byte) { | ||
v.Base = (*int8)(unsafe.Pointer(&b[0])) | ||
v.Len = uint64(len(b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris | ||
|
||
package socket | ||
|
||
type iovec struct{} | ||
|
||
func (v *iovec) set(b []byte) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build !linux,!netbsd | ||
|
||
package socket | ||
|
||
import "net" | ||
|
||
type mmsghdr struct{} | ||
|
||
type mmsghdrs []mmsghdr | ||
|
||
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error { | ||
return nil | ||
} | ||
|
||
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error { | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build linux netbsd | ||
|
||
package socket | ||
|
||
import "net" | ||
|
||
type mmsghdrs []mmsghdr | ||
|
||
func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr) []byte) error { | ||
for i := range hs { | ||
vs := make([]iovec, len(ms[i].Buffers)) | ||
var sa []byte | ||
if parseFn != nil { | ||
sa = make([]byte, sizeofSockaddrInet6) | ||
} | ||
if marshalFn != nil { | ||
sa = marshalFn(ms[i].Addr) | ||
} | ||
hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa) | ||
} | ||
return nil | ||
} | ||
|
||
func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (net.Addr, error), hint string) error { | ||
for i := range hs { | ||
ms[i].N = int(hs[i].Len) | ||
ms[i].NN = hs[i].Hdr.controllen() | ||
ms[i].Flags = hs[i].Hdr.flags() | ||
if parseFn != nil { | ||
var err error | ||
ms[i].Addr, err = parseFn(hs[i].Hdr.name(), hint) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build darwin dragonfly freebsd netbsd openbsd | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { | ||
for i := range vs { | ||
vs[i].set(bs[i]) | ||
} | ||
h.setIov(vs) | ||
if len(oob) > 0 { | ||
h.Control = (*byte)(unsafe.Pointer(&oob[0])) | ||
h.Controllen = uint32(len(oob)) | ||
} | ||
if sa != nil { | ||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) | ||
h.Namelen = uint32(len(sa)) | ||
} | ||
} | ||
|
||
func (h *msghdr) name() []byte { | ||
if h.Name != nil && h.Namelen > 0 { | ||
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen] | ||
} | ||
return nil | ||
} | ||
|
||
func (h *msghdr) controllen() int { | ||
return int(h.Controllen) | ||
} | ||
|
||
func (h *msghdr) flags() int { | ||
return int(h.Flags) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build darwin dragonfly freebsd netbsd | ||
|
||
package socket | ||
|
||
func (h *msghdr) setIov(vs []iovec) { | ||
h.Iov = &vs[0] | ||
h.Iovlen = int32(len(vs)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { | ||
for i := range vs { | ||
vs[i].set(bs[i]) | ||
} | ||
h.setIov(vs) | ||
if len(oob) > 0 { | ||
h.setControl(oob) | ||
} | ||
if sa != nil { | ||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) | ||
h.Namelen = uint32(len(sa)) | ||
} | ||
} | ||
|
||
func (h *msghdr) name() []byte { | ||
if h.Name != nil && h.Namelen > 0 { | ||
return (*[sizeofSockaddrInet6]byte)(unsafe.Pointer(h.Name))[:h.Namelen] | ||
} | ||
return nil | ||
} | ||
|
||
func (h *msghdr) controllen() int { | ||
return int(h.Controllen) | ||
} | ||
|
||
func (h *msghdr) flags() int { | ||
return int(h.Flags) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm mips mipsle 386 | ||
// +build linux | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (h *msghdr) setIov(vs []iovec) { | ||
h.Iov = &vs[0] | ||
h.Iovlen = uint32(len(vs)) | ||
} | ||
|
||
func (h *msghdr) setControl(b []byte) { | ||
h.Control = (*byte)(unsafe.Pointer(&b[0])) | ||
h.Controllen = uint32(len(b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x | ||
// +build linux | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (h *msghdr) setIov(vs []iovec) { | ||
h.Iov = &vs[0] | ||
h.Iovlen = uint64(len(vs)) | ||
} | ||
|
||
func (h *msghdr) setControl(b []byte) { | ||
h.Control = (*byte)(unsafe.Pointer(&b[0])) | ||
h.Controllen = uint64(len(b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package socket | ||
|
||
func (h *msghdr) setIov(vs []iovec) { | ||
h.Iov = &vs[0] | ||
h.Iovlen = uint32(len(vs)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// +build amd64 | ||
// +build solaris | ||
|
||
package socket | ||
|
||
import "unsafe" | ||
|
||
func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { | ||
for i := range vs { | ||
vs[i].set(bs[i]) | ||
} | ||
h.Iov = &vs[0] | ||
h.Iovlen = int32(len(vs)) | ||
if len(oob) > 0 { | ||
h.Accrights = (*int8)(unsafe.Pointer(&oob[0])) | ||
h.Accrightslen = int32(len(oob)) | ||
} | ||
if sa != nil { | ||
h.Name = (*byte)(unsafe.Pointer(&sa[0])) | ||
h.Namelen = uint32(len(sa)) | ||
} | ||
} | ||
|
||
func (h *msghdr) controllen() int { | ||
return int(h.Accrightslen) | ||
} | ||
|
||
func (h *msghdr) flags() int { | ||
return int(NativeEndian.Uint32(h.Pad_cgo_2[:])) | ||
} |
Oops, something went wrong.