加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang-goruntime与channel:高效的channel

发布时间:2020-12-16 19:15:35 所属栏目:大数据 来源:网络整理
导读:golang有两个非常大的特性,那就是goruntime与channel,这两个特性直接将开发人员从并发和线程同步中解放了出来,使高并发和线程同步之间代码的编写变得异常简单,并且占用资源少,同步传输效率高。 资源占用方面,goroutine 会从4096字节的初始栈内存占用开
                                                                                                     

golang有两个非常大的特性,那就是goruntime与channel,这两个特性直接将开发人员从并发和线程同步中解放了出来,使高并发和线程同步之间代码的编写变得异常简单,并且占用资源少,同步传输效率高。

资源占用方面,goroutine 会从4096字节的初始栈内存占用开始按需增长或缩减内存占用。同步传输效率方面,我曾经在松本行弘的《代码的未来》一书上看到一个简洁的例子(书上的代码中行末带有分号,目前golang中已经取消了源代码中行末的分号,由编译器代为添加,一行代码包含多个语句则需要分号分隔)。下列代码在原代码基础上做了适当调整。


package main  import (  "fmt"  "time" )  func chanFlow(left,right chan int,bufferLen int) {  if bufferLen <= 0 {   left <- 1 + <-right  } else {   for i := 0; i < bufferLen; i++ {    left <- 1 + <-right   }  } }  func main() {  nruntime := 100000  lastChan := make(chan int)   var left chan int = nil  right := lastChan   begin := time.Now()  fmt.Println("begin at:",begin)  for i := 0; i < nruntime; i++ {   left,right = right,make(chan int)   go chanFlow(left,right,0)  }   right <- 0  result := <-lastChan   end := time.Now()  fmt.Println("end   at:",end,time.Since(begin))  fmt.Println(result) }


程序创建了10w零1个无缓冲channel,10w个goruntime,数据在goruntime中从第一个channel流向最后一个channel,每流入一次数值加一。代码在我的笔记本(2.7 GHz Intel Core i5,8 GB 1867 MHz DDR3)运行结果如下:
begin at: 2016-08-28 14:42:04.972728029 +0800 CST
end at: 2016-08-28 14:42:05.454288408 +0800 CST 481.560725ms
耗时不到半秒。

上面的例子中使用的是无缓冲的channel,把代码修改为带1000个单位缓冲的channel再试试看,代码如下:


func chanFlow(left,bufferLen int) {...} func main() {  nruntime := 100000  chanBuffer := 1000  result := make([]int,100)   lastChan := make(chan int,chanBuffer)   var left chan int = nil  right := lastChan   begin := time.Now()  fmt.Println("begin at:",make(chan int,chanBuffer)   go chanFlow(left,chanBuffer)  }   for i := 0; i < chanBuffer; i++ {   right <- 0  }   for i := 0; i < chanBuffer; i++ {   result = append(result,<-lastChan)  }   end := time.Now()  fmt.Println("end   at:",time.Since(begin))  fmt.Println(result) }


运行结果如下:
begin at: 2016-08-28 14:54:09.352472708 +0800 CST
end at: 2016-08-28 14:54:14.155240335 +0800 CST 4.802767822s
不到5秒的时间,1000个数据在10w个goruntime中穿过了10w零1个channel。

而在实际生产中,更多的需要传递的数据是字符串,那么现在把代码再修改一下试试,代码如下:


package main  import (  "crypto/rand"  "encoding/base64"  "fmt"  "io"  "time" )  func chanFlow(left,right chan string,bufferLen int) {  if bufferLen <= 0 {   left <- <-right  } else {   for i := 0; i < bufferLen; i++ {    left <- <-right   }  } }  func genString() string {  b := make([]byte,32)  if _,err := io.ReadFull(rand.Reader,b); err != nil {   return ""  } else {   return base64.URLEncoding.EncodeToString(b)  } }  func main() {   nruntime := 100000  chanBuffer := 1000  result := make([]string,100)   lastChan := make(chan string,chanBuffer)  dataForChan := make([]string,chanBuffer)   for i := 0; i < chanBuffer; i++ {   dataForChan = append(dataForChan,genString())  }   var left chan string = nil  right := lastChan   begin := time.Now()  fmt.Println("begin at:",begin)  for i := 0; i < nruntime; i++ {    left,make(chan string,chanBuffer)  }  for i := 0; i < chanBuffer; i++ {   right <- dataForChan[i]  }   for i := 0; i < chanBuffer; i++ {   result = append(result,time.Since(begin))  fmt.Println(result) }



运行结果如下:

begin at: 2016-08-28 15:06:25.349599328 +0800 CST
end at: 2016-08-28 15:06:31.288183546 +0800 CST 5.938584364s
不到6秒的时间,1000个44字节的随机字符串在10w个goruntime中穿过了10w零1个channel。而1w个44字节的随机字符串在1w个goruntime中穿过了1w零1个channel耗时约为5秒。

以上可以看出,golang中数据在goruntime中通过channel同步的效率非常高。

本文来自:CSDN博客

感谢作者:changjixiong

查看原文:golang-goruntime与channel:高效的channel




查看原文:http://www.zoues.com/2016/10/20/golang-goruntime%e4%b8%8echannel%e9%ab%98%e6%95%88%e7%9a%84channel/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读