goroutine 花费的时间太长

时间:2020-12-21 11:05:31

标签: go

我的理解是,对于无缓冲通道 (jobs),您需要一个发送方和接收方,但我的代码顺序有误,需要很长时间才能完成。< br/> 我在这里错过了什么?

const numWorkers = 5
type workerJob struct {
    FirstID   string
    SecondID string
}

func worker(ctx *gin.Context, fs *firestore.Client, jobs <-chan *workerJob, done chan<- bool) {
    for job := range jobs {
        firstID := job.FirstID
        secondID := job.SecondID
        if err := saveUpdate(ctx, firstID, secondID, fs); err != nil {
            // handle error
        }
    }
    done <- true
}

func UpdateSomething(ctx *gin.Context) {
    fs, err := firestore.NewClient(ctx, "some_ID")
    if err != nil {
        // handle error
    }
    defer fs.Close()

    docsnaps, err := fs.CollectionGroup("someCollection").Where("someCondition", "==", true).Documents(ctx).GetAll()
    if err != nil {
        // handle error
    }
    uniqueSomethings := make(map[string]struct{})
    jobs := make(chan *workerJob)
    done := make(chan bool, numWorkers)
    for w := 1; w <= numWorkers; w++ {
         go worker(ctx, fs, jobs, done)
    }
    for _, docsnap := range docsnaps {
        var someType SomeType
        err := docsnap.DataTo(&someType)
        if err != nil { 
            // handle error
        }
        for _, prop := range someType.prop {
            if strings.Contains(prop.Name, "someString") {
                someID := prop.Name[strings.LastIndex(prop.Name, ":")+1:]
                if _, ok := uniqueSomethings[someID]; !ok {
                    uniqueSomethings[someID] = struct{}{}
                    job := &workerJob{
                        FirstID: dashboard.CustomerID,
                        SecondID:   someID[strings.Index(someID, "_")+1:],
                    }
                    jobs <- job
                }
            }
        }
    }
    close(jobs)
    for i := 1; i <= numWorkers; i++ {
        select {
        case <-done:
        }
    }
    return
}

1 个答案:

答案 0 :(得分:-1)

我不完全明白为什么,但我已经能够将时间减少 6 倍!我决定创建一个作业切片,然后创建一个具有预定义容量的通道 - 该切片的长度,然后遍历该切片并将作业发送到该通道,如下所示:

func UpdateSomething(ctx *gin.Context) {
    fs, err := firestore.NewClient(ctx, "some_ID")
    if err != nil {
        // handle error
    }
    defer fs.Close()

    docsnaps, err := fs.CollectionGroup("someCollection").Where("someCondition", "==", true).Documents(ctx).GetAll()
    if err != nil {
        // handle error
    }
    uniqueSomethings := make(map[string]struct{})
    jobsArr := make([]*workerJob, 0)
   
    for _, docsnap := range docsnaps {
        var someType SomeType
        err := docsnap.DataTo(&someType)
        if err != nil { 
            // handle error
        }
        for _, prop := range someType.prop {
            if strings.Contains(prop.Name, "someString") {
                someID := prop.Name[strings.LastIndex(prop.Name, ":")+1:]
                if _, ok := uniqueSomethings[someID]; !ok {
                    uniqueSomethings[someID] = struct{}{}
                    job := &workerJob{
                        FirstID: dashboard.CustomerID,
                        SecondID:   someID[strings.Index(someID, "_")+1:],
                    }
                    jobsArr = append(jobsArr, job)
                }
            }
        }
    }
    done := make(chan bool, numWorkers)
    jobs := make(chan *workerJob, len(jobsArr))
     
    for w := 1; w <= numWorkers; w++ {
         go worker(ctx, fs, jobs, done)
    }
    for _, job := range jobsArr {
        jobs <- job
    }
    close(jobs)
    for i := 1; i <= numWorkers; i++ {
        select {
        case <-done:
        }
    }
    return
}