Golang代码技巧

Author Avatar
Benson Yan 12月 29, 2017
  • 在其它设备中阅读本文章

nsq里的select写文件和socket

nsq里的select读

在nsq中,需要读取磁盘上或者内存中的消息,一般人都是先判断内存、磁盘中有没有数据,再尝试读取,然而,nsq另辟蹊径使用了select语句,把CSP模式用到了极致

1
2
3
4
5
6
7
8
9
select {
case msg = <-c.memoryMsgChan: //尝试从内存中读取
case buf = <-c.backend.ReadChan(): //尝试磁盘上读取
msg, err = decodeMessage(buf)
if err != nil {
c.ctx.nsqd.logf("ERROR: failed to decode message - %s", err)
continue
}
}

fasthttp里对header的处理

fasthttp对于header的处理fasthttp为什么会比net.http快,其中一个原因就是fasthttp并没有完全地解析所有的http请求header数据。这种做法也称作lazy loading。首先我们从header的struct开始看起吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type RequestHeader struct {
//bla.....
contentLength int
contentLengthBytes []byte

method []byte
requestURI []byte
host []byte
contentType []byte
userAgent []byte

h []argsKV
bufKV argsKV

cookies []argsKV

rawHeaders []byte
}

可能大家都很奇怪,Request里没有string,明明method、host都可以用string啊,这是由于string是不可变类型,而从Reader中读出的[]byte是可变类型,因此,从[]byte转化为string时是有copy和alloc行为的。虽然数据量小时,没有什么影响,但是构建高并发系统时,这些小的数据就会变大变多,让gc不堪重负。request中还有一个特殊的

1
2
3
4
argsKVtype argsKV struct {
key []byte
value []byte
}

其实和上面的理由是一样的,net.http中使用了map[string]string来存储各种其他参数,这就需要alloc,为了达成zero alloc,fasthttp采用了遍历所有header参数来返回,其实也有一定的考虑,那就是大部分的header数量其实都不多,而每次对于短key对比只需要若干个CPU周期,因此算是合理的tradeoff(详见bytes.Equal汇编实现 )

This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:https://blog.bensonfx.cc/2017/12/29/Golang代码技巧/