Показаны сообщения с ярлыком Go компилятор. Показать все сообщения
Показаны сообщения с ярлыком Go компилятор. Показать все сообщения

суббота, 29 февраля 2020 г.

Релиз Go 1.14: runtime и компилятор

Runtime (среда времени выполнения)

Релиз Go 1.14 улучшает производительность большинства применений defer, что приводит к почти нулевым издержкам по сравнению с непосредственным вызовом отложенной функции. В результате, теперь defer можно использовать в коде, критичном к производительности, без лишних проблем.

Goroutines теперь асинхронно вытесняются. В результате циклы без вызовов функций больше не могут заблокировать планировщик или существенно задержать сборку мусора. Это поддерживается на всех платформах, кроме windows/arm, darwin/arm, js/wasm и plan9/*.

Следствием реализации вытеснения является то, что в системах Unix, включая системы Linux и macOS, программы, собранные (build) с Go 1.14, будут получать больше сигналов, чем программы, собранные (build) с более ранними релизами. Это означает, что программы, использующие такие пакеты, как syscall или golang.org/x/sys/unix, увидят, что более медленные системные вызовы завершаются с ошибками EINTR. Этим программам придется каким-то образом обрабатывать эти ошибки, скорее всего, повторяя цикл, чтобы повторить системный вызов.

Распределитель страниц является более эффективным и вызывает значительно меньше конфликтов блокировки при высоких значениях GOMAXPROCS. Это наиболее заметно, так как более низкая задержка и более высокая пропускная способность для больших распределений выполняются параллельно и с высокой скоростью.

Внутренние таймеры, используемые time.After, time.Tick, net.Conn.SetDeadline и схожие, более эффективны, с меньшим количеством конфликтов блокировки и меньшим количеством переключений контекста. Это улучшение производительности, которое не должно вызывать видимых изменений.

Компилятор

В релизе Go 1.14 добавлена ​​опция -d=checkptr в качестве параметра времени компиляции для добавления инструментария для проверки того, что код Go соответствует unsafe.Pointer правилам безопасности динамически. Эта опция включается по умолчанию (кроме Windows) с флагами -race или -msan и может быть отключена с -gcflags=all=-d=checkptr=0. В частности, -d=checkptr проверяет следующее:

  1. При преобразовании unsafe.Pointer в *T результирующий указатель должен быть выровнен соответствующим образом для T.
  2. Если результат арифметики указателя указывает на объект кучи (heap) Go, один из операндов с типом unsafe.Pointer должен указывать на тот же объект.

Использование -d=checkptr в настоящее время не рекомендуется в Windows, потому что это вызывает ложные предупреждения в стандартной библиотеке.

Компилятор теперь может генерировать машиночитаемые журналы ключевых оптимизаций, используя флаг -json, включая встраивание (inlining), escape-анализ, исключение bounds-check (исключение проверки границ) и nil-check.

Детальный escape-анализ (-m=2) теперь снова работает. Ранее он был исключен из новой реализации escape-анализа в предыдущем релизе.

Все символы Go в двоичных файлах macOS теперь начинаются с подчеркивания, следуя соглашениям платформы.

Этот выпуск включает в себя экспериментальную поддержку встроенного компилятором инструментария покрытия для фаззинга. Этот API может измениться в будущих релизах.

Исключение проверки границ теперь использует информацию из создания среза и может исключать проверки для индексов с типами, меньшими, чем int.


Читайте также:


Купить gopher

среда, 10 апреля 2019 г.

Запуск скриптов с помощью Go

Всем известно, что Go не скриптовый язык. Но при желании его можно использовать для выполнения скриптов как и любой из интерпретируемых языков как Python или PHP. Для этого можно воспользоваться командой go run myScript.go (для запуска скрипта myScript.go). Конечно при этом будет происходить компиляция и будет создан исполняемый бинарный файл, но после завершения программы он будет автоматически удален и не останется на жестком диске. Вот простой пример скрипта с названием myScript.go:

package main

import "fmt"

func main() {
 fmt.Println("Всем привет, это скрипт.")
 fmt.Println("Всем пока, программа завершена.")
}

Теперь запустим наш скрипт:

go run myScript.go

Всем привет, это скрипт.
Всем пока, программа завершена.

Проверим содержимое текущей папки:

ls

myScript.go

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


Читайте также:


четверг, 21 февраля 2019 г.

Go FAQ: Можно ли прекратить жалобы компилятора на неиспользованную переменную/импорт?

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

Тем не менее, при разработке кода это обычное дело - создавать такие ситуации временно, и это может быть раздражающим, редактировать их до того как программа скомпилируется.

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

Есть две причины отсутствия предупреждений.
Во-первых, если оно того стоит - жаловаться - стоит исправить код. (И если это не стоит исправлять - не стоит упоминать об этом.)
Во-вторых, наличие компилятора, генерирующего предупреждения побуждает реализацию предупреждать о слабых случаях, что может сделать компиляцию шумной, маскируя реальные ошибки, которые должны быть исправлены.

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

import "unused"

// Это объявление помечает импорт как использованный 
// путем ссылки на элемент из пакета.
var _ = unused.Item  // TODO: Удалить перед коммитом!

func main() {
    debugData := debug.Profile()
    _ = debugData // Использовано только в ходе отладки.
    ....
}

В настоящее время большинство программистов на Go используют инструмент, goimports, который автоматически переписывает исходный файл Go для правильного импорта, устраняя проблемы неиспользованного импорта на практике. Эта программа легко подключается к большинству редакторов для автоматического запуска при написании исходного файла Go.


Читайте также:


Go FAQ: Почему простая программа становится таким большим бинарным файлом после компиляции?

Компоновщик (linker) в цепочке инструментов gc создает статически связанные бинарные файлы по умолчанию. Все бинарные файлы Go, следовательно, включают Go runtime, наряду с информацией о runtime типах, необходимой для поддержки динамической проверки типов, отражения (reflection) и даже для stack trace'ов времени паники (panic-time).

Простая программа на языке C "hello, world", скомпилированная и статически связанная с использованием gcc в Linux составляет около 750 кБ, включая реализацию printf. Эквивалентная Go программа с использованием fmt.Printf весит пару мегабайт, но она включает более мощную поддержку во время выполнения (run-time support), а также информация о типах и отладочную информацию.

Программа на Go, скомпилированная с помощью gc, может быть связана с флагом -ldflags=-w для отключения генерации DWARF, удаляя отладочную информацию из бинарного файла, но без других потерь функциональности. Это может существенно уменьшить размер бинарного файла.


Читайте также:


Go FAQ: Какие компиляторы используются для создания самих Go компиляторов?

Есть несколько производственных компиляторов для Go и ряд других в разработке для различных платформ.

Компилятор по умолчанию, gc, включен в распространяемый Go как часть поддержки go команды. Gc изначально был написан на C из-за трудностей с загрузкой - понадобился компилятор Go, чтобы настроить среду Go. Но дела пошли дальше, и после выпуска Go 1.5 компилятор был Go программой. Компилятор был преобразован из C в Go с использованием инструментов автоматического перевода. Таким образом, компилятор теперь "самодостаточен", что означает, что приходится сталкиваться с проблемой начальной загрузки. Решение состоит в том, чтобы иметь уже работающую установку Go, как обычно делают с работающей установкой Си.

Gc написан на Go с парсером рекурсивного спуска и использует собственный загрузчик, также написанный на Go, но на основе загрузчика Plan 9 для создания бинарных файлов ELF/Mach-O/PE.

В начале проекта разработчики языка рассматривали возможность использования LLVM для gc но решили, что он слишком большой и медленный для удовлетворения цели производительности. В ретроспективе, если бы начать с LLVM, сложнее представить некоторые из ABI и связанных с ними изменений, таких как управление стеком, которое требуется Go, но не является частью стандартной настройки C.

Компилятор Gccgo - это интерфейс, написанный на C++ с парсером рекурсивного спуска, соединенным с стандартным бекендом GCC.

Go оказался хорошим языком для реализации компилятора Go, хотя это не было его первоначальной целью. Отсутствие самостоятельного хостинга позволило дизайну Go сосредоточиться на своем первоначальном варианте использования, который был сетевым сервером. Если бы разработчики языка решили, что Go должен скомпилировать себя на ранней стадии, в конечном итоге мог бы получиться язык, предназначенный больше для построения компилятора, это достойная цель, но не та, которая была у разработчиков языка изначально.

Хотя gc не использует их, нативный лексер и парсер доступны в пакете go, а также есть встроенная программа проверки типов.


Читайте также: