Запустите ограниченное число работников, но синхронизируйте count++: простое добавление go создаст гонку и даст неверный счётчик.
Ускорение выполнения большого количества сетевых запросов
Запустите ограниченное число работников, но синхронизируйте count++: простое добавление go создаст гонку и даст неверный счётчик.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо повысить скорость выполнения функции networkRequest(), которая имитирует сетевой запрос, задерживая выполнение на time.Sleep(time.Millisecond), и увеличивает глобальный счётчик count.
import (
"fmt"
"time"
)
const numRequests = 1000
var count int
func networkRequest() {
time.Sleep(time.Millisecond)
count++;
}
func main() {
defer timer() ()
for i := 0 ; i < numRequests; i++ {
networkRequest()
}
}
func timer() func () {
start :=time.Now()
return func(){
fmt.Println("count %v took %v\n", count, time.Since(start))
}
}
Ответ
Запустите ограниченное число работников, но синхронизируйте count++: простое добавление go создаст гонку и даст неверный счётчик.
Например, 100 работников получают задания из канала. Ниже полный минимальный вариант с тем же имитатором задержки:
package main
import (
"fmt"
"sync"
"time"
)
var count int
var mu sync.Mutex
func networkRequest() {
time.Sleep(time.Millisecond)
mu.Lock()
count++
mu.Unlock()
}
func main() {
start := time.Now()
jobs := make(chan struct{})
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range jobs { networkRequest() }
}()
}
for i := 0; i < 1000; i++ { jobs <- struct{}{} }
close(jobs)
wg.Wait()
fmt.Printf("count %v took %v\n", count, time.Since(start))
}
После Wait число равно 1000. Реальное время не обязано быть ровно 10 мс: влияют планировщик и таймеры. В исходном timer для подстановки %v тоже нужен Printf, не Println.