Go выпущен в 2019 годуGo 1.12иGo 1.13. Большинство изменений в Go 1.13 касаются цепочки инструментов, среды выполнения и реализации библиотек. Через полгода официально вышел Go 1.14.
Как и предыдущая версия, эта версия сохраняет обещание совместимости с Go 1, большинство обновлений в этой версии связаны с повышением производительности цепочки инструментов и библиотеки времени выполнения. В общем, комиссия по прежнему оптимизируется на существующем базисе, дженерик, которого все ждут, еще не пришел, давайте посмотрим на новые изменения ниже. Основные обновления заключаются в следующем:
- Поддержка модулей в командах Go теперь готова к работе
- Встраивание интерфейса с перекрывающимися наборами методов
- отложить улучшение производительности
- горутина поддерживает асинхронное вытеснение
- смена инструмента
- time.Timer производительность таймера значительно улучшена
Поддержка модулей в командах Go теперь готова к работе
Поддержка модулей теперь доступна в командах Go для производственного использования, и всем пользователям рекомендуется перейти на модули Go для управления зависимостями.
Встраивание интерфейса с перекрывающимися наборами методов
Go 1.14 теперь позволяет встраивать интерфейсы с перекрывающимися наборами методов: методы из встроенного интерфейса могут иметь то же имя и сигнатуру, что и метод, уже присутствующий во (встроенном) интерфейсе.
До Go 1.14 следующие определения компилировались с ошибкой.
type ReadWriteCloser interface {
io.ReadCloser
io.WriteCloser
}
Потому что метод Close в io.ReadCloser и io.WriteCloser дублируется. Go 1.14 позволяет встраивать в интерфейс методы с одинаковой сигнатурой. Как и раньше, методы, явно объявленные в интерфейсе, должны оставаться уникальными.
отложить улучшение производительности
Go 1.14 повышает производительность большинства применений отсрочки почти без накладных расходов! defer уже можно использовать в сценариях с высокими требованиями к производительности.
Что касается отсрочки, то в Go 1.13 были сделаны некоторые оптимизации, по сравнению с Go 1.12 производительность отсрочки в большинстве случаев повысилась на 30%. И это улучшение в Go 1.14 стало еще эффективнее!
горутина поддерживает асинхронное вытеснение
Модель G-M-P, используемая планировщиком. Ниже приведены связанные понятия:
- G (Горутина): горутина, созданная по ключевому слову go
- M (Machine): называется Machine в Go, что можно понимать как рабочий поток.
- P (процессор): процессор P является средним уровнем между потоком M и горутиной (не ЦП).
M должен удерживать P для выполнения кода в G. P имеет свою собственную локальную очередь выполнения, состоящую из исполняемых G. Принцип работы планировщика языка Go заключается в выборе горутины в начале очереди в очереди процессора P и поместите его в поток Executed on M, на приведенном выше рисунке показана связь между потоком M, процессором P и горутиной.
G, поддерживаемый каждым P, может быть несбалансированным. Планировщик также поддерживает глобальную очередь G. Когда P завершает выполнение локальной задачи G, он попытается получить задачу G из глобальной очереди для запуска (требуется блокировка). Когда ни локальная, ни глобальная очереди не имеют выполняемых задач, она попытается украсть G из других P в локальную очередь для запуска (кража задач).
В версии Go 1.1 планировщик не поддерживает упреждающее планирование и может полагаться только на горутину для активного отказа от ресурсов ЦП.Существуют очень серьезные проблемы с планированием:
- Отдельная горутина всегда может занять поток для запуска и не будет переключаться на другие горутины, вызывая проблемы с голоданием.
- Сборка мусора должна приостановить всю программу (Stop-the-world, STW), если нет вытеснения, ожидание может занять несколько минут, что приведет к сбою всей программы.
В Go 1.12 компилятор вставляет функции в определенное время и запускает вытеснение через вызовы функций в качестве точки входа, реализуя совместное вытесняющее планирование. Однако в этом методе планирования есть некоторые пограничные случаи, которые требуют активного взаимодействия вызовов функций, например следующие примеры:
import (
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(1)
go func() { //创建一个goroutine并挂起
for {
}
}()
time.Sleep(time.Millisecond) //main goroutine 优先调用了 休眠
println("OK")
}
В этот момент единственный P отправится на выполнение горутины, созданной циклом for, и основная горутина больше никогда не будет запланирована. Другими словами, до Go1.14 приведенный выше код никогда не выводит OK. Это связано с тем, что совместное вытесняющее планирование, реализованное в Go 1.12, не будет вытеснять горутину, которая добровольно не отказывается от прав на выполнение и не участвует ни в каких вызовах функций.
Go1.14 решает вышеуказанные проблемы, реализуя истинное вытесняющее планирование на основе сигналов.Это очень большое изменение.Команда Go реорганизовала существующую логику и добавила в горутину новые состояния и поля для поддержки вытеснения. Циклы без вызовов функций больше не могут вызывать взаимоблокировки планировщика или влиять на сборщик мусора. Это поддерживается на всех платформах, кроме Windows/arm, darwin/arm, js/wasm и plan9/*.
В результате реализации вытеснения в системах Unix, включая системы Linux и macOS, программы, созданные с помощью Go 1.14, будут получать больше сигналов, чем программы, созданные с более ранними версиями. Это означает, что программы, использующие такие пакеты, как syscall или golang.org/x/sys/unix, будут видеть более медленные системные вызовы с ошибками EINTR. Этим программам придется каким-то образом обрабатывать эти ошибки, скорее всего, зациклившись, повторив системный вызов. Для получения дополнительной информации об этом см. man 7 signal для систем Linux или аналогичную документацию для других систем.
смена инструмента
Что касается улучшения инструментов в Go1.14, я в основном говорю о go mod и go test. Должностные лица Go определенно хотят, чтобы разработчики использовали официальные инструменты управления пакетами. Go1.14 улучшил многие функции. go мод в основном внес следующие улучшения:
- несовместимые версии: если последняя версия модуля содержит файл go.mod, go get больше не будет обновляться до несовместимой основной версии этого модуля, если эта версия явно не запрошена или не была запрошена. При выборке напрямую из системы контроля версий go list также игнорирует несовместимые версии этого модуля, но может включать эти версии, если об этом сообщает агент.
- Обслуживание файла go.mod: кроме
go mod tidy
Команда go вне этого больше не удаляет директиву require, которая указывает косвенную версию зависимости, которая уже подразумевается другими зависимостями основного модуля. Кромеgo mod tidy
Команды Go за пределами этого больше не редактируют файл go.mod, если изменения носят только косметический характер. - Загрузка модуля: в модульном режиме команда go поддерживает репозитории SVN, а команда go теперь включает сводки сообщений об ошибках в виде простого текста от прокси-серверов модулей и других HTTP-серверов. Сообщение об ошибке будет отображаться только в том случае, если сообщение об ошибке имеет допустимую кодировку UTF-8 и содержит графические символы и пробелы.
go test -v теперь передает вывод t.Log вместо вывода в конце всех тестовых данных.
time.Timer производительность таймера значительно улучшена
В версиях до Go 1.10 язык Go использовал глобальную четырехъядерную кучу для обслуживания всех таймеров. Внутренний таймер, используемый time.after, time.Tick, net.Conn.SetDeadline и другими, более эффективен, с меньшей конкуренцией за блокировку и меньшим переключением контекста. Это улучшение производительности, и оно не вызовет видимых пользователем изменений.
Конкретное улучшение тут вы сами понимаете, оно относительно сложное, автор изучает последнюю реализацию, и об этой части я расскажу позже.
резюме
Go 1.14 имеет много других изменений:
- Изменения в WebAssembly
- Изменения в пакете Reflect
- Множество других важных изменений в пакетах (math, http и т. д.)
Предложение по обработке ошибок в языке Go получило поддержку многих людей в сообществе, но есть и много противников.Вывод таков: Go отказался от этого предложения! Эти идеи не были полностью разработаны, особенно с учетом стоимости реализации изменения языка, поэтому языковая команда Go в последнее время не рассматривала реализацию перечислений и неизменяемых типов.
Go1.14 также имеет некоторые запланированные, но незавершенные работы Go1.14 пытается оптимизировать распределитель страниц, что может значительно уменьшить количество конфликтов при блокировке, когда значение GOMAXPROCS относительно велико. Это изменение имеет большое значение, может значительно улучшить параллелизм Go и еще больше повысить производительность таймеров. Однако из-за сложности реализации есть некоторые проблемы, которые не могут быть решены вовремя, и это будет отложено до завершения Go1.15.
Подробный журнал выпуска Go 1.14 см.golang.org/doc/go1.14.
Ссылаться на
- go 1.14 golang.org/doc/go1.14
- Что касается Go1.14, вы должны знать об улучшениях производительности и новых функциях.