Golang中重新open 已经被close的chan管道

2017-12-07 11:32:17来源:作者:人点击

分享

最近忽发奇想,在Golang中怎么把,已经关闭的管道再次打开。这样就避免了,每次都要make一个新的chan,节省内存申请和GC的时间,查看go的源代码,经过简单地摸索后,实现了,示例代码如下。func TestUnsafe(t *testing.T) {
c1 = make(chan struct{}, 10)
c1 <- struct{}{}
<-c1
close(c1)
p := (*unsafe.Pointer)(unsafe.Pointer(&c1))
c := (*hchan)(*p)
c.closed = 0//打开被关闭的chan
c1 <- struct{}{}
<-c1
}
func TestSafe(t *testing.T) {
c1 = make(chan struct{}, 10)
c1 <- struct{}{}
<-c1
close(c1)
p := (*unsafe.Pointer)(unsafe.Pointer(&c1))
c := (*hchan)(*p)
atomic.CompareAndSwapUint32(&c.closed, 1, 0) //打开被关闭的chan
c1 <- struct{}{}
<-c1
}

最终代码 发布到 github.com/yireyun/go-openc,有兴趣的朋友可以看看。

这种做法最大的缺点是如果go的runtime的数据结构发生变化,将不再可行。因此增加了在init方法中检测的go内核数据结构是否发生变化的代码,性能测试结果如下。

BenchmarkMakeCloseChan-4
20000000
90.9 ns/op
--- BENCH: BenchmarkMakeCloseChan-4(每次新建在关闭的性能)
go1.7.4, Times: 1, use: 0s 0s/op
go1.7.4, Times: 100, use: 0s 0s/op
go1.7.4, Times: 10000, use:998.3µs 99ns/op
go1.7.4, Times: 1000000, use:91.0664ms 91ns/op
go1.7.4, Times:20000000, use: 1.8185449s 90ns/op
BenchmarkCloseOpenChan-4
50000000
29.5 ns/op
--- BENCH: BenchmarkCloseOpenChan-4(非安全打开的性能)
go1.7.4, Times: 1, use: 0s 0s/op
go1.7.4, Times: 100, use: 0s 0s/op
go1.7.4, Times: 10000, use: 0s 0s/op
go1.7.4, Times: 1000000, use:28.5199ms 28ns/op
go1.7.4, Times:50000000, use:1.473497s 29ns/op
BenchmarkCloseOpenChanSync-4
30000000
44.9 ns/op
--- BENCH: BenchmarkCloseOpenChanSync-4(安全打开的性能)
go1.7.4, Times: 1, use: 0s 0s/op
go1.7.4, Times: 100, use: 0s 0s/op
go1.7.4, Times: 10000, use:498.2µs 49ns/op
go1.7.4, Times: 1000000, use:47.5278ms 47ns/op
go1.7.4, Times:30000000, use: 1.3479236s 44ns/op
PASS
ok
github.com/yireyun/go-openc
8.235s

相关文章

    无相关信息

微信扫一扫

第七城市微信公众平台