Go 性能优化技巧 6/10

作者: qyuhen | 来源:发表于2016-04-30 13:18 被阅读390次

Go 使用 channel 实现 CSP 模型。处理双方仅关注通道和数据本身,无需理会对方身份和数量,以此实现结构性解耦。在各文宣中都有 “Don't communicate by sharing memory, share memory by communicating.” 这类说法。但这并非鼓励我们不分场合,教条地使用 channel。

在我看来,channel 多数时候适用于结构层面,而非单个区域的数据处理。原话中 “communicate” 本就表明一种 “message-passing”,而非 “lock-free”。所以,它并非用来取代 mutex,各自有不同的使用场景。

有关 channel 实现方式,可参考《Go 学习笔记》第五版,下卷《源码剖析》。

从实现角度看,channel 算是一种很 “重” 的实现。在小粒度层面,其性能真算不得好。我们可用一个常见示例测试一下:用 channel 实现并发安全的计数器,或序号生成器。

性能测试结果表明,差异远比想的要大得多。单就此例而言,还可以用原子操作(atomic)进一步优化。

如果说 channel 适用于结构层面解耦,那么 mutex 则适合保护语句级别的数据安全。至于 atomic,虽然也可实现 lock-free 结构,但处理起来要复杂得多(比如 ABA 等问题),也未必就比 mutex 快很多。还有,sync.Mutex 本就没有使用内核实现,而是像 Futex 那样,直接在用户空间以 atomic 操作完成,因为 runtime 没有任何理由将剩余 CPU 时间片还给内核。

从没一种技术或技巧适用于所有场合。无论是表达,或者选型,都不应该脱离实际场景(上下文)。另外,就本系列的优化技巧而言,除非真有必要,否则大可不必理会这些 “奇技淫巧”。至于担心能否适应未来变化,我觉得多余。因为无论是架构、算法,亦或者是这些技巧,你本就应该有相应的机制确保在 “变化” 发生时第一时间获知。再者说,技巧并非照抄,无非多种思路而已。知其形,明其意,方为正理。

——未完待续


请关注微信公众号

相关文章

  • Go 性能优化技巧 6/10

    Go 使用 channel 实现 CSP 模型。处理双方仅关注通道和数据本身,无需理会对方身份和数量,以此实现结构...

  • Go 性能优化技巧 10/10

    垃圾回收不是万能的,Go 一样存在资源泄露问题。 1SetFinalizer 虽然垃圾回收器能很好地处理循环引用,...

  • Go 性能优化技巧 2/10

    对于一些初学者,自知道 Go 里面的 array 以 pass-by-value 方式传递后,就莫名地引起 “恐慌...

  • Go 性能优化技巧 3/10

    内置 map 类型是必须的。首先,该类型使用频率很高;其次,可借助 runtime 实现深层次优化(比如说字符串转...

  • Go 性能优化技巧 4/10

    延迟调用(defer)确实是一种 “优雅” 机制。可简化代码,并确保即便发生 panic 依然会被执行。如将 pa...

  • Go 性能优化技巧 9/10

    作为内置类型,通道(channel)从运行时得到很多支持,其自身设计也算得上精巧。但不管怎么说,它本质上依旧是一种...

  • Go性能优化技巧 1/10

    字符串(string)作为一种不可变类型,在与字节数组(slice, [ ]byte)转换时需付出 “沉重” 代价...

  • Go 性能优化技巧 8/10

    尽管反射(reflect)存在性能问题,但依然被频繁使用,以弥补静态语言在动态行为上的不足。只是某些时候,我们须对...

  • Go 性能优化技巧 7/10

    接口的用途无需多言。但这并不意味着可在任何场合使用接口,要知道通过接口调用和普通调用存在很大差别。首先,相比静态绑...

  • Go 性能优化技巧 5/10

    闭包(closure)也是很常见的编码模式,因它隐式携带上下文环境变量,因此可让算法代码变得更加简洁。 但任何 “...

网友评论

    本文标题:Go 性能优化技巧 6/10

    本文链接:https://www.haomeiwen.com/subject/mmskrttx.html