10.2.3 并发控制

函数是编译器的编译单元,也是编译器的并发单元,可以通过编译参数 -c 指定编译器编译的并发数量。并发控制的代码如下:

func compileFunctions() {
    if len(compilequeue) == 0 {
        return
    }

    // 控制编译顺序
    if race.Enabled {
        // Randomize compilation order to try to shake out races.
        tmp := make([]*ir.Func, len(compilequeue))
        perm := rand.Perm(len(compilequeue))
        for i, v := range perm {
            tmp[v] = compilequeue[i]
        }
        copy(compilequeue, tmp)
    } else {
        // Compile the longest functions first,
        // since they're most likely to be the slowest.
        // This helps avoid stragglers.
        sort.Slice(compilequeue, func(i, j int) bool {
            return len(compilequeue[i].Body) > len(compilequeue[j].Body)
        })
    }

    // We queue up a goroutine per function that needs to be
    // compiled, but require them to grab an available worker ID
    // before doing any substantial work to limit parallelism.
    workerIDs := make(chan int, base.Flag.LowerC)
    for i := 0; i < base.Flag.LowerC; i++ {
        workerIDs <- i
    }

    var wg sync.WaitGroup
    var asyncCompile func(*ir.Func)
    asyncCompile = func(fn *ir.Func) {
        wg.Add(1)
        go func() {
            worker := <-workerIDs
            ssagen.Compile(fn, worker)
            workerIDs <- worker

            // Done compiling fn. Schedule it's closures for compilation.
            for _, closure := range fn.Closures {
                asyncCompile(closure)
            }
            wg.Done()
        }()
    }

    types.CalcSizeDisabled = true // not safe to calculate sizes concurrently
    base.Ctxt.InParallel = true
    for _, fn := range compilequeue {
        asyncCompile(fn)
    }
    compilequeue = nil
    wg.Wait()
    base.Ctxt.InParallel = false
    types.CalcSizeDisabled = false
}

可见 -c 控制并发数量,然后函数 asyncCompile 通过 workerIDssync.WaitGroup 进行并发同步。

最后更新于