Выполняется ли запись в карту мьютексов с несколькими подпрограммами быстрее, чем в одну? и почему?

#go #go-map

#Вперед #перейти на карту #go-map

Вопрос:

У меня есть SyncMap, определенный следующим образом:

 type SyncMap struct {
    sync.Mutex
    Map map[int]string
}
  

И теперь я записываю в нее двумя способами: одной подпрограммой и несколькими подпрограммами с мьютексом. коды следующим образом:

 smap := SyncMap{}
smap.Map = make(map[int]string)
t1 := time.Now()
for i := 0; i < 10000; i   {
    smap.Map[i] = strconv.Itoa(i)
}
elapsed := time.Since(t1)
fmt.Println("t1 elapsed", elapsed)
  
 s2map := SyncMap{}
s2map.Map = make(map[int]string)
t2 := time.Now()
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
    defer wg.Done()
    for i := 0; i < 5000; i   {
        s2map.Lock()
        s2map.Map[i] = strconv.Itoa(i)
        s2map.Unlock()
    }
}()
go func() {
    defer wg.Done()
    for i := 5000; i < 10000; i   {
        s2map.Lock()
        s2map.Map[i] = strconv.Itoa(i)
        s2map.Unlock()
    }
}()
wg.Wait()
elapsed2 := time.Since(t2)
fmt.Println("t2 elapsed", elapsed2)
  

Выводите следующим образом:

 t1 elapsed 5.0363ms
t2 elapsed 5.9353ms
  

Попробуйте servel time, t1 всегда быстрее, чем t2.
Итак, мой вопрос таков, как указано в названии.

Могу ли я понять, что это связано с использованием блокировки мьютекса? В данном случае SyncMap или sync.Карта в пакете go предназначена только для безопасного написания программ, а не для повышения эффективности? И есть ли какой-то способ повысить эффективность при написании карты с несколькими маршрутами?

Спасибо ~

Ответ №1:

Это довольно просто. Во втором сценарии, с двумя подпрограммами, из-за мьютекса одновременно на карту может быть записана только одна из подпрограмм. Так что на самом деле это не сильно отличается от простого выполнения этого последовательно с помощью одной подпрограммы. В любой момент времени только одна подпрограмма будет что-либо делать. Счетчики и циклирование вообще не занимают много времени, поэтому их, по сути, можно игнорировать, именно запись на карту занимает большую часть времени.

Однако у вас также есть дополнительные расходы на блокировку и 10000 операций блокировки и разблокировки, которые довольно дороги. Таким образом, это означает, что в целом это будет медленнее.

В целом, использование большего количества подпрограмм не ускоряет процесс, если в любой момент времени выполняется только одна подпрограмма.

Для большей эффективности используйте карту получше, например, это или this. Созданная вами карта вообще не допускает параллелизма.