mirror of https://github.com/golang/go.git
120 lines
2.4 KiB
Go
120 lines
2.4 KiB
Go
// Copyright 2021 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 poll_test
|
|
|
|
import (
|
|
"internal/poll"
|
|
"internal/syscall/unix"
|
|
"runtime"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// checkPipes returns true if all pipes are closed properly, false otherwise.
|
|
func checkPipes(fds []int) bool {
|
|
for _, fd := range fds {
|
|
// Check if each pipe fd has been closed.
|
|
_, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0)
|
|
if errno == 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestSplicePipePool(t *testing.T) {
|
|
const N = 64
|
|
var (
|
|
p *poll.SplicePipe
|
|
ps []*poll.SplicePipe
|
|
fds []int
|
|
err error
|
|
)
|
|
for i := 0; i < N; i++ {
|
|
p, _, err = poll.GetPipe()
|
|
if err != nil {
|
|
t.Skip("failed to create pipe, skip this test")
|
|
}
|
|
_, pwfd := poll.GetPipeFds(p)
|
|
fds = append(fds, pwfd)
|
|
ps = append(ps, p)
|
|
}
|
|
for _, p = range ps {
|
|
poll.PutPipe(p)
|
|
}
|
|
ps = nil
|
|
p = nil
|
|
|
|
// Exploit the timeout of "go test" as a timer for the subsequent verification.
|
|
timeout := 5 * time.Minute
|
|
if deadline, ok := t.Deadline(); ok {
|
|
timeout = deadline.Sub(time.Now())
|
|
timeout -= timeout / 10 // Leave 10% headroom for cleanup.
|
|
}
|
|
expiredTime := time.NewTimer(timeout)
|
|
defer expiredTime.Stop()
|
|
|
|
// Trigger garbage collection repeatedly, waiting for all pipes in sync.Pool
|
|
// to either be deallocated and closed, or to time out.
|
|
for {
|
|
runtime.GC()
|
|
time.Sleep(10 * time.Millisecond)
|
|
if checkPipes(fds) {
|
|
break
|
|
}
|
|
select {
|
|
case <-expiredTime.C:
|
|
t.Fatal("at least one pipe is still open")
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkSplicePipe(b *testing.B) {
|
|
b.Run("SplicePipeWithPool", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
p, _, err := poll.GetPipe()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
poll.PutPipe(p)
|
|
}
|
|
})
|
|
b.Run("SplicePipeWithoutPool", func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
p := poll.NewPipe()
|
|
if p == nil {
|
|
b.Skip("newPipe returned nil")
|
|
}
|
|
poll.DestroyPipe(p)
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSplicePipePoolParallel(b *testing.B) {
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
p, _, err := poll.GetPipe()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
poll.PutPipe(p)
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSplicePipeNativeParallel(b *testing.B) {
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
p := poll.NewPipe()
|
|
if p == nil {
|
|
b.Skip("newPipe returned nil")
|
|
}
|
|
poll.DestroyPipe(p)
|
|
}
|
|
})
|
|
}
|