В настоящее время я изучаю Go и начал переписывать программу генерации тестовых данных, которую я изначально написал на Java. Я был заинтригован возможностями каналов / потоков в Go, так как многие из написанных мною программ были сосредоточены на нагрузочном тестировании системы / записи различных метрик.
Здесь я создаю некоторые данные для записи в файл CSV. Я начал с генерации всех данных, а затем передал их для записи в файл. Затем я подумал, что попытаюсь реализовать канал, чтобы данные можно было записывать, пока они еще генерируются.
Это сработало - это почти исключило накладные расходы при генерации данных сначала и , а затем их записи. Однако я обнаружил, что это работало, только если у меня был канал с буфером, достаточно большим, чтобы справиться со всеми генерируемыми тестовыми данными: c := make(chan string, count)
, где count - это тот же размер, что и число строк тестовых данных, которые я генерирую.
Итак, на мой вопрос: я регулярно генерирую миллионы записей тестовых данных (приложения для нагрузочного тестирования) - должен ли я использовать канал с таким большим буфером? Я не могу найти много об ограничениях на размер буфера?
Выполнение нижеприведенного подсчета 10 м завершается за ~ 59,5 с; генерация данных заранее и запись их в файл занимает ~ 62 с; использование длины буфера 1 - 100 занимает ~ 80 с.
const externalRefPrefix = "Ref"
const fileName = "citizens.csv"
var counter int32 = 0
func WriteCitizensForApplication(applicationId string, count int) {
file, err := os.Create(fileName)
if err != nil {
panic(err)
}
defer file.Close()
c := make(chan string, count)
go generateCitizens(applicationId, count, c)
for line := range c {
file.WriteString(line)
}
}
func generateCitizens(applicationId string, count int, c chan string) {
for i := 0; i < count; i++ {
c <- fmt.Sprintf("%v%v\n", applicationId, generateExternalRef())
}
close(c)
}
func generateExternalRef() string {
atomic.AddInt32(&COUNTER, 1)
return fmt.Sprintf("%v%08d", externalRefPrefix, counter)
}