Длина буфера канала Go - лучшая практика - PullRequest
0 голосов
/ 24 апреля 2018

В настоящее время я изучаю 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)
}
...