предисловие
Причина инцидента в том, что однажды технический директор вдруг сказал мне, что ЦП программы в производственной среде немного высоковат, ключ в том, что нагрузки сейчас нет, а ЦП того же кода в среде разработки намного ниже.
Излишне говорить, что должно быть что-то не так.
Технический директор также сказал, что он преуспел, и загрузка процессора была самой высокой.runtime.futex, также опубликовал соответствующую статьюКто занимает 30% этого ядра ЦП — довольно неожиданная проблема с производительностью Go, в шутку сказал, что может нагрузка на систему большая, и эта проблема ушла. Потому что в исходном тексте сказано:
Следует отметить, что эта проблема вызвана тем, что система простаивает и нет горутин, которые можно было бы запланировать. Очевидно, что когда система занята, то есть когда ресурсы ЦП действительно ценны, упомянутых выше 30% накладных расходов ЦП не существует, потому что велика вероятность того, что горутины будут доступны для планирования, а нет нужно сделать тяжелую работу, позволив М. работать.
Потом он «свалил» мне горшок и дал изучить его. Ведь нагрузка на среду разработки не такая уж и высокая, а вот на ЦП вполне нормально.
анализировать
Сначала я понятия не имел, но следуя подсказкам технического директора, я начал искатьruntime.futex, почти во всех из них упоминается следующий пример кода, который может сильно загружать ЦП:
var ticker = time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
var counter = 0
for {
select {
case <-serverDone:
return
case <-ticker.C:
counter += 1
}
}
Этот код указал мне какое-то направление, и я начал глобальный поиск кода для time.NewTicker.
По стечению обстоятельств я действительно нашел некоторые, и одна из настроек времени бегущей строки очень проблематична.
options = append(options, metrics.BatchInterval(time.Duration(conf.BatchInterval)))
здесьtime.Duration(conf.BatchInterval) не указывает единицу измерения, это уровень наносекунды (наносекунды).Сопрограмма тикера работает, не вызывая взаимоблокировки.Можно только сказать, что производительность сервера Linux хорошая.
Позже я пошел по вайнам и обнаружил, что этот интервал на самом деле является интервалом выборки прометуса, который включается только в продакшене, что также может объяснить, почему тот же код имеет проблемы только в продакшене.
Решение
Первоначальное решение очень простое, просто добавьте к этому интервалу единицу, а затем немного увеличьте его, и в настоящее время мы не уделяем много внимания данным о производительности прометуса, поэтому мы не уверены, не слишком ли велик интервал выборки в 50 мс. большой.
Суммировать
Несмотря на то, что первопричина проблемы найдена, есть еще возможности для улучшения.Например, если конфигурация рабочей программы и программы разработки различаются в начале, проблема может быть решена быстрее.