前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用channel流提前预处理部分信息,和普通的线性处理会有巨大的差别吗

使用channel流提前预处理部分信息,和普通的线性处理会有巨大的差别吗

作者头像
天地一小儒
发布2022-12-28 14:02:39
1990
发布2022-12-28 14:02:39
举报
文章被收录于专栏:信且诚心之动

研究课题

最近在考虑优化程序的执行时间时,考虑过一个问题,就是,如果有一个并发处理的程序,每次调用时,都需要做一部分预处理,比如,发送http请求时,要先组装request,那么每一次都组装好了再发请求和通过channel预处理request,发送是从channel里面获取会不会性能有很大提高呢?

测试代码

为此,我做了一个小程序检验,代码如下:

代码语言:javascript
复制
package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    count, concurrcy := 10, 1

    costs := make([]time.Duration, count)
    cost1s := make([]time.Duration, count)
    for index := 0; index < 10; index++ {
        // directly
        var wg sync.WaitGroup
        wg.Add(concurrcy)
        now := time.Now()
        for index := 0; index < concurrcy; index++ {
            go func() {
                directlyGet()
                doAnother()
                wg.Done()
            }()
        }
        wg.Wait()
        costs[index] = time.Since(now)

        // channel
        var wg1 sync.WaitGroup
        wg1.Add(concurrcy)
        now1 := time.Now()
        for index := 0; index < concurrcy; index++ {
            go func() {
                <-channelGet()
                doAnother()
                wg1.Done()
            }()
        }
        wg1.Wait()
        cost1s[index] = time.Since(now1)
    }

    var cost, cost1 float64
    for index := 0; index < count; index++ {
        cost += costs[index].Seconds()
        cost1 += cost1s[index].Seconds()
    }
    fmt.Println("cost(avg, ms):", cost*1000/float64(count))
    fmt.Println("cost1(avg, ms):", cost1*1000/float64(count))
    fmt.Println("((cost1-cost)/cost)(%):", ((cost1 - cost) / cost))
}

func directlyGet() string {
    doOther()
    return "result"
}

func doOther() {
    time.Sleep(20 * time.Millisecond)
}

func doAnother() {
    time.Sleep(20 * time.Millisecond)
}

func channelGet() <-chan string {
    stream := make(chan string)
    go func() {
        defer close(stream)
        doOther()
        stream <- "result"
    }()

    return stream
}

direcltyGet是每次使用时,都要doOther完成,然后才能doAnother;而channelGet则是将doOther和doAnother并发处理,简单来说就是当在doAnother的时候,另一个goroutine已经在doOther了。那这个结果是怎么样的呢?这个程序现在主要影响的参数有2,1是concurrcy-并发量,而是doOther:doAnother,即预处理部分相对于后面的处理所占的比例。count是用来消除单次执行的影响,求取花费时间平均值。

实验结果

经过几次调整后的结果列入下表(单位:ms):

并发量count

消耗比 doOther:doAnother

平均线性处理 cost

平均预处理cost1

消耗比1 cost1:cost

1

1:0.001

20.863898799999998

21.0200263

0.74831411663098596

1

1:1

41.1631734

41.448019099999996

0.6919915946033516

1

1:50

1022.5822461

1022.6867288000001

0.01021753510767501

50

1:0.001

21.314165699999997

21.501593299999996

0.8793569621165047

50

1:1

42.6392575

43.419844499999996

1.8306768123248847

50

1:50

1022.7240038

1023.0811119

0.03491734805022551

5000

1:0.001

23.6074675

27.948086

18.38663338200085

5000

1:1

47.451019800000005

51.9780305

9.540386527161635

5000

1:50

1026.7172483

1028.0245165000001

0.12732504515382329

总结

在doOther固定20ms消耗的情况下(更大消耗无明显影响,因为消耗时间是按比例计算),经过channel预处理之后所花费时间无明显减少(比例为负数),反而在大并发量情况下还有所增加,猜测是由于放大goroutine之间的切换调度,即阻塞与唤醒等。因此,在无必要情况下,如将输入转化成流形式,或者有并发共享内存等的影响,可不必刻意追求将输入转化为channel流

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 研究课题
  • 测试代码
  • 实验结果
  • 总结
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档