作者回复: 👍
作者回复: 👍
作者回复: 好问题。使用sync.Pool时,复用内存对象当前数据可能会造成数据错乱的情况。因此如何处理这种问题,要看pool中的对象是什么以及如何用? 像我们这里,pool中对象是一个Submit的指针,而submit的结构如下: type Submit struct { ID string Payload []byte } 这个结构在每次decode时都会被全量覆盖: func (s *Submit) Decode(pktBody []byte) error { s.ID = string(pktBody[:8]) s.Payload = pktBody[8:] return nil } 也就是说虽然put时没有重置,但取出后重置了。 换成其他pool中对象和其他场景,的确需要考虑是否需要重置对象,以及是在put时还是get时进行重置。
作者回复: 是减少socket read系统调用的次数,也就是说增加buf read前,每次read,无论read 1个字节,还是read 100个字节,都要执行一次sys call。而增加buf read后的read会看buf中是否有足够的数据,如果有数据满足read需求,就不会执行syscall去读取底层的socket数据。当然之所以能做这么是因为bufio.Reader.Read每次从底层socket读取的数据并不是上层传入的大小,默认值为defaultBufSize ,即4096。
作者回复: 书也买了啊,哈哈,嫡系了🤝
作者回复: 👍
作者回复: "管它黑猫白猫,能抓住老鼠就是好猫",至少目前sync.Pool能在一定场景下帮助我们提升性能。 go与java虽然都是gc语言,但由于类型系统的差异,gc所面对的环境也不同,有些事情不能以强弱来论。比如java gc做分代,而go gc没有分代,不是go gc不想做分代,而是经过实测分代对go gc的提升有限,因为go的许多生命周期很短的临时对象经过逃逸分析后是分配在栈上的,完全不需要在堆上分配。 当然和java比,go在gc方面的打磨时间还远远不够。这反过来说也是好事,目前go gc已经很不错了,未来只能更强大。作为Go应用开发者,我们将来可以做到“躺赢”:)。
作者回复: 在linux上跑一个小时,也没有出现问题。以前还真没在mac上跑过,我抽时间调查一下。
作者回复: 主要是因为io.ReadFull这个函数,可以查看一下它的manual。
作者回复: 可以试着将你收到的所有数据按字节逐个dump出来。可以使用hex.Dump这个函数。 btw同问:有遇到过这种错误情况的么?