Помните процесс устранения неполадок с высокой загрузкой процессора программы golang

Go

предисловие

Причина инцидента в том, что однажды технический директор вдруг сказал мне, что ЦП программы в производственной среде немного высоковат, ключ в том, что нагрузки сейчас нет, а ЦП того же кода в среде разработки намного ниже.

Излишне говорить, что должно быть что-то не так.

Технический директор также сказал, что он преуспел, и загрузка процессора была самой высокой.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 мс. большой.

Суммировать

Несмотря на то, что первопричина проблемы найдена, есть еще возможности для улучшения.Например, если конфигурация рабочей программы и программы разработки различаются в начале, проблема может быть решена быстрее.

Справочная статья