可以对该代码进行以下优化:
在循环内部将 datasetInfo 初始化为指针类型,以避免在追加到切片中时发生值拷贝。
使用并发 goroutine 的方式去处理每个 datasetObj,可以提高 CPU 利用率和程序的执行速度。
对于快速的数据集属性列表,可以使用 sync.Map 来存储。因为这是并发安全的。
下面是优化后的代码示例:
var fastDatasetList []*dataset.Dataset
slowDatasetChan := make(chan *dataset.Dataset, int(datasetCount)-len(datasetIdMap))
// 存储数据集信息的临时 map
datasetInfoMap := &sync.Map{}
var wg sync.WaitGroup
for _, datasetObj := range datasetObjList {
wg.Add(1)
go func(datasetObj *citadel.Dataset) {
defer wg.Done()
dataCount, err := citadel.CountDataset(l.ctx, l.svcCtx, datasetObj.DatasetID)
if err != nil {
err = code.WithCodeMsg(code.Internal)
return
}
datasetInfoPtr := &dataset.Dataset{
ID: citadel.StringFromId(datasetObj.DatasetID),
Name: datasetObj.Name,
ParsePdf: datasetObj.ParsePdf,
CreateAt: datasetObj.CreateAt.UTC().Unix(),
UpdateAt: datasetObj.UpdateAt.UTC().Unix(),
Note: datasetObj.Note,
Count: dataset.DatasetCount{
Total: int(dataCount.Total),
Labeled: int(dataCount.Labeled),
Classified: int(dataCount.Classified),
Synthetic: int(dataCount.Synthetic),
},
}
_ = json.Unmarshal(datasetObj.Configure, &datasetInfoPtr.Configure)
// 存储快速的数据集属性列表
if _, ok := datasetIdMap[datasetObj.DatasetID]; ok {
datasetInfoMap.Store(datasetObj.DatasetID, datasetInfoPtr)
} else {
// 通过通道将非快速数据集属性列表追加到切片中
slowDatasetChan <- datasetInfoPtr
}
}(datasetObj)
}
// 等待所有 goroutine 执行完成
wg.Wait()
// 遍历存储快速数据集属性列表的临时 map
datasetInfoMap.Range(func(key, value interface{}) bool {
fastDatasetList = append(fastDatasetList, value.(*dataset.Dataset))
return true
})
// 关闭通道,以便处理器知道没有更多数据需要接收
close(slowDatasetChan)
// 迭代通道来收集慢速数据集属性列表
for datasetInfoPtr := range slowDatasetChan {
slowDatasetList = append(slowDatasetList, *datasetInfoPtr)
}
在这个例子中,我们使用了一个临时的 sync.Map,存储快速数据集属性列表。这可以避免多次增量地向切片追加数据,因为这会导致切片的重新分配和拷贝。
通过并发 goroutine 的方式去处理每个 datasetObj,我们可以同时处理多个任务,并减少总执行时间。使用通道来收集非快速数据集属性列表也是一种有效的方法,它可以防止 goroutine 因为无法写入数据而被阻塞。