Skip to content

Commit

Permalink
错字及排版修改
Browse files Browse the repository at this point in the history
  • Loading branch information
lintanghui committed Mar 28, 2016
1 parent bbfb859 commit a24865e
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 28 deletions.
2 changes: 1 addition & 1 deletion chapter01/01.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

有时候我们需要传递一个io.ReadCloser的实例,而我们现在有一个io.Reader的实例,比如:strings.Reader,这个时候NopCloser就派上用场了。它包装一个io.Reader,返回一个io.ReadCloser,而相应的Close方法啥也不做,只是返回nil。

比如,在标准库net/http包中的NewRequest,接收一个io.Reader的body,而实际上,Request的Body类型的是io.ReadCloser,因此,代码内部进行了判断,如果传递的io.Reader也实现了io.ReadCloser接口,则转换,否则通过ioutil.NoCloser包装转换一下。相关代码如下:
比如,在标准库net/http包中的NewRequest,接收一个io.Reader的body,而实际上,Request的Body的类型是io.ReadCloser,因此,代码内部进行了判断,如果传递的io.Reader也实现了io.ReadCloser接口,则转换,否则通过ioutil.NoCloser包装转换一下。相关代码如下:

rc, ok := body.(io.ReadCloser)
if !ok && body != nil {
Expand Down
49 changes: 25 additions & 24 deletions chapter16/16.01.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,31 @@ func (ss *ServerList) PickServer(key string) (net.Addr, error) {

答案是不会的,sync.Pool的回收是有的,它是在系统自动GC的时候,触发pool.go中的poolCleanup函数。

```golang
func poolCleanup() {
for i, p := range allPools {
allPools[i] = nil
for i := 0; i < int(p.localSize); i++ {
l := indexLocal(p.local, i)
l.private = nil
for j := range l.shared {
l.shared[j] = nil
}
l.shared = nil
}
p.local = nil
p.localSize = 0
}
allPools = []*Pool{}
}
```

这个函数会把Pool中所有goroutine创建的对象都进行销毁。

那这里另外一个问题也凸显出来了,很可能我上一步刚往pool中PUT一个对象之后,下一步GC触发,导致pool的GET函数获取不到PUT进去的对象。
这个时候,GET函数就会调用New函数,临时创建出一个对象,并存放到pool中。

根据以上结论,sync.Pool其实不适合用来做持久保存的对象池(比如连接池)。它更适合用来做临时对象池,目的是为了降低GC的压力。

连接池性能测试

Expand Down Expand Up @@ -165,30 +190,6 @@ ok _/E_/MyGo/sync 3.345s
```

通过性能测试可以清楚地看到,使用连接池消耗的CPU时间远远小于每次手动分配内存。
```golang
func poolCleanup() {
for i, p := range allPools {
allPools[i] = nil
for i := 0; i < int(p.localSize); i++ {
l := indexLocal(p.local, i)
l.private = nil
for j := range l.shared {
l.shared[j] = nil
}
l.shared = nil
}
p.local = nil
p.localSize = 0
}
allPools = []*Pool{}
}
```
这个函数会把Pool中所有goroutine创建的对象都进行销毁。

那这里另外一个问题也凸显出来了,很可能我上一步刚往pool中PUT一个对象之后,下一步GC触发,导致pool的GET函数获取不到PUT进去的对象。
这个时候,GET函数就会调用New函数,临时创建出一个对象,并存放到pool中。

根据以上结论,sync.Pool其实不适合用来做持久保存的对象池(比如连接池)。它更适合用来做临时对象池,目的是为了降低GC的压力。

## Once ##

Expand Down
6 changes: 3 additions & 3 deletions preface.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
- 8.5 archive/zip — zip归档访问
* 第九章 [测试](chapter09/09.0.md)
- 9.1 [testing - 测试基本使用接口](chapter09/09.1.md)
* 第九章 加解密
* 第十章 进程、线程与goroutine
* 第十一章 网络通信与互联网(internet)
* 第十二章 email
Expand All @@ -48,5 +47,6 @@
- 15.1 buildin
- 15.2 [unsafe — 非类型安全操作](chapter15/15.02.md)
* 第十六章 同步
- 15.1 [sync - 处理同步需求](chapter16/16.01.md)
- 15.2 [sync/atomic - 原子操作](chapter16/16.02.md)
- 16.1 [sync - 处理同步需求](chapter16/16.01.md)
- 16.2 [sync/atomic - 原子操作](chapter16/16.02.md)
* 第十七章 加解密

0 comments on commit a24865e

Please sign in to comment.