Я пытаюсь установить время, необходимое для выполнения параллельных запросов. Мои результаты времени примерно в четыре раза медленнее, чем сообщает ab2.Сроки запросов в goroutines
Я пробовал запросы на синхронизацию двумя разными способами, обе из которых приводят к аналогичным результатам (которые далеки от результатов ab2). Чтобы привести пример, ab2 сообщит, что самый длинный запрос длится 2 миллисекунды на локальном сервере, тогда как этот код будет сообщать до 4,5 миллисекунд. Кстати, вся база кода доступна here.
Как правильно правильно запросить время?
Метод 1: выбор времени включает в себя больше, чем просто просьбу
this commit С.
// Let's spawn all the requests, with their respective concurrency.
wg.Add(r.Repeat)
r.doneWg.Add(r.Repeat)
for rno := 1; rno <= r.Repeat; rno++ {
go func(no int, greq goreq.Request) {
r.ongoingReqs <- struct{}{} // Adding sentinel value to limit concurrency.
startTime := time.Now()
greq.Uri = r.URL.Generate()
gresp, err := greq.Do()
if err != nil {
log.Critical("could not send request to #%d %s: %s", no, r.URL, err)
} else if no < r.Repeat {
// We're always using the last response for the next batch of requests.
gresp.Body.Close()
}
<-r.ongoingReqs // We're done, let's make room for the next request.
resp := Response{Response: gresp, duration: time.Now().Sub(startTime)}
// Let's add that request to the list of completed requests.
r.doneChan <- &resp
runtime.Gosched()
}(rno, greq)
}
Способ 2: использование внутренней функции с Defer заявление
От this commit.
// Let's spawn all the requests, with their respective concurrency.
wg.Add(r.Repeat)
r.doneWg.Add(r.Repeat)
for rno := 1; rno <= r.Repeat; rno++ {
go func(no int, greq goreq.Request) {
r.ongoingReqs <- struct{}{} // Adding sentinel value to limit concurrency.
greq.Uri = r.URL.Generate()
var duration time.Duration
gresp, err := func(dur *time.Duration) (gresp *goreq.Response, err error) {
defer func(startTime time.Time) { *dur = time.Now().Sub(startTime) }(time.Now())
return greq.Do()
}(&duration)
if err != nil {
log.Critical("could not send request to #%d %s: %s", no, r.URL, err)
} else if no < r.Repeat {
// We're always using the last response for the next batch of requests.
gresp.Body.Close()
}
<-r.ongoingReqs // We're done, let's make room for the next request.
resp := Response{Response: gresp, duration: duration}
// Let's add that request to the list of completed requests.
r.doneChan <- &resp
runtime.Gosched()
}(rno, greq)
}
Я смотрел this question, что не помогло.
Если вы пытаетесь создать тест, добавление другого слоя поверх пакета http с «goreq» кажется контрпродуктивным. Сначала попробуйте со стандартным пакетом http, а затем профиль, если еще не пропало время. Ряд генераторов нагрузки HTTP был написан в Go с хорошими результатами. – JimB
Сервер вообще возвращает * любой * контент в теле ответа? – JimB
@JimB, да сервер может вернуть контент. И этот генератор нагрузки может фактически использовать возвращенные данные для последующих запросов. – ChrisR