递归函数内的多线程速度较慢

问题描述 投票:0回答:1
var m sync.Mutex

func recurseDirectoriesMultiThread(wg *sync.WaitGroup, photoPaths *[]string, directory string) {
    defer wg.Done()
    items, _ := os.ReadDir(directory)
    for _, item := range items {
        if item.IsDir() {
            wg.Add(1)
            go recurseDirectoriesMultiThread(wg, photoPaths, directory+"/"+item.Name())
        } else {
            // handle file
            m.Lock()
            *photoPaths = append(*photoPaths, directory+"/"+item.Name())
            m.Unlock()
        }
    }

}
func recurseDirectories(photoPaths *[]string, directory string) {
    items, _ := os.ReadDir(directory)
    for _, item := range items {
        if item.IsDir() {
            recurseDirectories(photoPaths, directory+"/"+item.Name())
        } else {
            // handle file
            *photoPaths = append(*photoPaths, directory+"/"+item.Name())
        }
    }
}

func main() {
    args := os.Args
    fmt.Println(args[1])
    path := args[1]

    stringSlice1 := make([]string, 0) // slice
    start := time.Now()
    recurseDirectories(&stringSlice1, path)
    fmt.Println("Single thread time " + time.Since(start).String())
    fmt.Println("Number of files " + strconv.Itoa(len(stringSlice1)))

    stringSlice2 := make([]string, 0) // slice
    wg := new(sync.WaitGroup)
    wg.Add(1)
    start = time.Now()
    recurseDirectoriesMultiThread(wg, &stringSlice2, path)
    wg.Wait()
    fmt.Println("Mulit thread time " + time.Since(start).String())
    fmt.Println("Number of files " + strconv.Itoa(len(stringSlice2)))
}

我想尝试一个项目来了解有关 goroutine 和通道的更多信息。我认为系统文件扫描器是获取目录中所有文件名的好主意。尽管现在我发现它可能不如我想象的那么高效 https://stackoverflow.com/a/41687429/13970153 因为无论我的方法如何,在系统调用级别都会有文件 i/o 锁定。不管怎样,出于某种奇怪的原因,我发现我的多线程方法的性能一直低于正常的递归方法。我认为至少在某种程度上会更快?

输出:

Mulit thread time 224.196833ms
Number of files 3123
Single thread time 147.0

Mulit thread time 228.218042ms
Number of files 3123
Single thread time 149.666041ms
Number of files 3123

Mulit thread time 185.23275ms
Number of files 3123
Single thread time 147.412958ms
Number of files 3123

大家有什么想法吗?

我没有看到在这里使用通道的原因,因为我可以锁定和解锁互斥锁

photoPaths

go concurrency parallel-processing system-calls
1个回答
0
投票

由于您对公共列表的每次添加都使用了锁定/解锁,因此所有 goroutine 可能都会互相等待写入列表。因此,你的算法并没有真正从多个 goroutine 中受益,因为查找文件所花费的时间与等待写入列表所花费的时间相当。

尝试从每个 goroutine 返回一个包含多个文件的新切片,并使用锁将一个列表附加到另一个列表,然后进行测量。这应该会增加并行性,因为每个 goroutine 将独立工作来填充新切片。

© www.soinside.com 2019 - 2024. All rights reserved.