Пришло время для выпуска новой версии языка Go снова! Главный герой на этот разGo 1.10.
Когда-то это было много сусликов вGo 1.8,Go 1.9Пришло время угадать, существует ли версия, в конце концов, минорная версия вот-вот превратится в двузначную. От первой дизайнерской почты языка Go до наших днейдесять лет, особенно после того, как в последние годы язык Go пережил взрывной рост и в основном закрепил позицию первого облачного родного языка, люди получили более новое и более глубокое понимание языка Go и в то же время лучше понимают этот язык программирования. , Также ожидаются дополнительные улучшения и оптимизации языка. Место Go2 в сердце Гофера увеличивается, покаRuss CoxсуществуетGopherCon 2017Объявлено в основной команде GoСтратегия развития Go2, мы поняли, что:О, и Go1 будет продолжаться какое-то время, даже долгое время. В феврале 2018 года у нас будет релиз Go 1.10..
отПерейти версии 1.4Сначала я даже не думал, что смогу«Несколько изменений, на которые стоит обратить внимание в Go x.x»Эта серия была написана до Go 1.10. Но теперь кажется, что эта серия продолжится, и могут быть Go 1.11, Go 1.12... и даже различные версии после эволюции в Go2.
Идти отВышла версия 1.0С того дня он послушался себя«Изменить и не изменить»философия. Инвариант - идти«Go1 обещает совместимость»Строгое соблюдение изменений — это более точная и терпеливая полировка производительности языка, среды выполнения, сборщика мусора, инструментов и стандартных библиотек. Этот выпуск Go Версия 1.10 продолжает эту философию, сосредоточив внимание на улучшении среды выполнения, инструментов и стандартной библиотеки. Далее я рассмотрю изменения, на которые стоит обратить внимание в грядущем выпуске Go 1.10.
1. Язык
Go language SpecактуаленПерейти на языкЕдинственный стандарт спецификации языка, хотя его строгость все же несколько далека от тех, что написаны в стандартной форме ISO (например, спецификации языка C и языка C++). Поэтому оптимизация go spec заключается в упорной работе над строгостью. Главный редактор текущей спецификации — один из трёх разработчиков языка Go.Robert Griesemer, он в го 1.10 Цикл до спецификацииСделано больше улучшений в строгости языковых концепций..
1. Явно определить репрезентативность
существуетProperties of types and valuesГлава, Роберт Гриземер явно вводит новый терминRepresentability, здесь переводится какПредставительность. этого терминавводитьНикаких грамматических изменений не было внесено, только более точная интерпретация спецификации. Определение репрезентативности указывает несколько условий, которые выполняются, когда в спецификации появляется «константа x может быть представлена значением типа T», особенно для типов с плавающей запятой и сложных типов. Вот выдержка (не переведена):
A constant x is representable by a value of type T if one of the following conditions applies:
- x is in the set of values determined by T.
- T is a floating-point type and x can be rounded to T's precision without overflow. Rounding uses IEEE 754 round-to-even rules but with an IEEE negative zero further simplified to an unsigned zero. Note that constant values never result in an IEEE negative zero, NaN, or infinity.
- T is a complex type, and x's components real(x) and imag(x) are representable by values of T's component type (float32 or float64).
2. Уточнить тип в некоторых специфических контекстах, когда константа неопределенного типа используется в качестве левого операнда операции сдвига (сдвига) непостоянной битовой операции
Хотя это не так строго, как стандартная спецификация ISO, любая языковая спецификация имеет порог для понимания. этоУлучшения касаются констант с неопределенными типами., при использовании в качестве левого операнда операции сдвига непостоянного бита, когда результат выражения сдвига используется в качестве нижнего индекса в выражении нижнего индекса, нижнего индекса в выражении среза или параметра размера в вызове функции make, эта константа будет присвоена типу int. Давайте рассмотрим пример, который более нагляден:
// go1.10-examples/spec/untypedconst.go
package main
var (
s uint = 2
)
func main() {
a := make([]int, 10)
a[1.0<<s] = 4
}
В приведенном выше примере сосредоточьтесь наa[1.0 << s] = 4Эта строка, эта строка отвечает нескольким условиям:
- 1.0
- Число битов, сдвинутых выражением сдвига, равно s, а s является переменной и непостоянной, поэтому это непостоянная операция сдвига битов;
- 1.0 является нетипизированной константой и используется как левый операнд выражения сдвига.
В Go 1.9.2 указанная выше программа компилируется следующим образом:
// go 1.9.2编译器build:
$go build untypedconst.go
# command-line-arguments
./untypedconst.go:9:7: invalid operation: 1 << s (shift of type float64)
В Go 1.9.2 константе 1.0 компилятор присваивал тип float64, что приводило к ошибке компиляции. В Go 1.10, согласно последней спецификации, 1.0 присваивается тип int, и компиляция проходит гладко.
Но как только она выйдет из контекста индексов, константа 1.0 все равно будет распознана компилятором как float64.Например, в следующем коде 1.0
// go1.10-examples/spec/untypedconst.go
package main
import "fmt"
var (
s uint = 2
)
func main() {
a := make([]int, 10)
a[1.0<<s] = 4
fmt.Println(1.0<<s)
}
// go 1.10rc2编译器build:
$go build untypedconst.go
# command-line-arguments
./untypedconst.go:12:17: invalid operation: 1 << s (shift of type float64)
./untypedconst.go:12:17: cannot use 1 << s as type interface {} in argument to fmt.Println
3. Уточните, является ли предварительно объявленный тип определенным типом или псевдонимом.
Иди вВерсия 1.9Синтаксис псевдонима был введен в , а также был введен определенный тип (вместо именованного типа) и тип псевдонима, а реализация некоторых предварительно объявленных типов была скорректирована с использованием синтаксиса псевдонима. В спецификации Go 1.10 Гриземер идет дальше.Ясно, какие предварительно объявленные типы являются псевдонимами.:
目前内置的predeclared type只有两个类型是alias type:
byte alias for uint8
rune alias for int32
Остальные предварительно объявленные типы являются определенными типами.
4. Убрать ограничение на тип T в выражении метода: T.m в спецификации
На этот раз спецификация находится за компилятором. Go 1.9.2 может успешно скомпилировать и запустить следующий код:
//go1.10-examples/spec/methodexpression.go
package main
import "fmt"
type foo struct{}
func (foo)f() {
fmt.Println("i am foo")
}
func main() {
interface{f()}.f(foo{})
}
Но в спецификации Go 1.9.2 определение выражения метода выглядит следующим образом:
Go 1.9.2 spec:
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
В спецификации Go 1.9.2 говорится, что форма выражения метода: T в T.m может использовать только Typename, а не реализацию типа в приведенном выше коде. В спецификации Go 1.10Снимите ограничение на T в выражении метода, чтобы реализация type также могла вызывать метод как T, синхронизируясь с фактическим поведением реализации компилятора:
Go 1.10rc2 spec:
MethodExpr = ReceiverType "." MethodName .
ReceiverType = Type .
Но в настоящее время компилятор Go 1.10 rc2 все еще существует.один вопрос, давайте посмотрим на следующий код:
//go1.10-examples/spec/methodexpression1.go
package main
func main() {
(*struct{ error }).Error(nil)
}
Собирая этот исходный код с помощью Go 110rc2, я получаю следующую ошибку:
$go build methodexpression1.go
# command-line-arguments
go.(*struct { error }).Error: call to external function
main.main: relocation target go.(*struct { error }).Error not defined
main.main: undefined: "go.(*struct { error }).Error"
Эта проблема уже существуетissueСоответственно статус по-прежнему Open.
2. Инструменты
Язык Go имеет набор инструментов, которому могут позавидовать другие популярные языки программирования.Каждое обновление версии Go будет улучшать набор инструментов как с точки зрения функциональности, так и с точки зрения удобства разработки.
1. GOROOT по умолчанию
следующийПерейти версии 1.8После введения GOPATH по умолчанию версия Go 1.10 продолжает улучшать опыт разработчиков инструмента Go и еще больше снижает порог для использования новичками.Введен GOROOT по умолчанию: то есть разработчику не нужно явно устанавливать GOROOT переменная окружения, и программа go будет автоматически следовать своему пути.Выведите путь к GOROOT. Таким образом, Gophers может распаковать загруженный предварительно скомпилированный установочный пакет Go и поместить его в любой локальный путь, единственное, что нужно сделать, это поместить путь бинарной программы go в переменную окружения PATH. Например, мы разархивируем установочный пакет go1.10rc2 по следующему пути:
➜ /Users/tony/.bin/go1.10rc2 $ls
AUTHORS LICENSE VERSION blog/ lib/ robots.txt
CONTRIBUTING.md PATENTS api/ doc/ misc/ src/
CONTRIBUTORS README.md bin/ favicon.ico pkg/ test/
После установки PATH мы просматриваем значения GOROOT и других связанных переменных, автоматически выводимых командой go env:
$go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/tony/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/tony/go"
GORACE=""
GOROOT="/Users/tony/.bin/go1.10rc2"
GOTMPDIR=""
GOTOOLDIR="/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -gno-record-gcc-switches -fno-common"
Из вывода видно, что go правильно нашел путь установки и получил информацию GOROOT.
2. Увеличьте переменную GOTMPDIR
В выходных данных команды go env выше мы обнаружили незнакомую переменную: GOTMPDIR, значение которой по умолчанию равно пустой строке. этопеременная GOTMPDIR— это переменная, недавно представленная в Go 1.10 для установки пути к временным файлам, созданным и используемым инструментом Go. Некоторые люди могут сказать: Эта переменная не кажется необходимой, просто используйте системный путь /tmp напрямую. Но есть как минимум две проблемы с компиляцией и выполнением скомпилированной программы в пути /tmp,эти вопросыНа самом деле это уже давно существует в истории проблем go:
- Некоторые машины установлены по пути /tmpНет разрешения на выполнение (установить noexec)
- Некоторые машины имеют ограниченное пространство в /tmp
Мы знаем, что по умолчанию команда go build and go run установит временный каталог WORK в /tmp для компиляции исходного кода и выполнения скомпилированной программы, вывод из процесса компиляции и выполнения простейшего исходного кода helloworld ниже (переменная WORK), мы можем видеть это:
// on ubuntu 16.04
# go run -x hello.go
WORK=/tmp/go-build001434392
mkdir -p $WORK/b001/
... ...
mkdir -p $WORK/b001/exe/
cd .
/root/.bin/go1.10rc2/pkg/tool/linux_amd64/link -o $WORK/b001/exe/hello -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=fcYMWp_1J2Xqgzc_Vdga/UpnEUti07R2GzG8dUU3x/MLkSlJVesZhf2kQUaDUU/fcYMWp_1J2Xqgzc_Vdga -extld=gcc /root/.cache/go-build/9f/9f34be2dbcc3f8a62dd6efd6d35be18ecdcbc49e3c8b52b003ecd72b6264e19e-d
$WORK/b001/exe/hello
Я лично столкнулся с проблемой, что место на системном диске, предоставляемое поставщиком IaaS, слишком мало (настройка и модификация не разрешены), что приводит к сбою построения и выполнения приложения Go. Давайте настроим GOTMPDIR и посмотрим на результат. Мы устанавливаем GOTMPDIR в ~/.gotmp, и после того, как это вступит в силу, пересобираем приведенный выше код helloworld:
# go build -x hello.go
WORK=/root/.gotmp/go-build452283009
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
... ...
mkdir -p $WORK/b001/exe/
cd .
/root/.bin/go1.10rc2/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=kO-wBNzMZmfHCKzMDziw/jCGBCt7bcrS5NEN-cR4H/8-du6iTQz8uPH3UC-FtB/kO-wBNzMZmfHCKzMDziw -extld=gcc $WORK/b001/_pkg_.a
/root/.bin/go1.10rc2/pkg/tool/linux_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
rm -r $WORK/b001/
Как видите, инструмент go перенесен в GOTMPDIR, который мы установили для сборки и выполнения.
3. Реализовать инкрементное построение через кеш, чтобы повысить производительность инструментов go.
Высокая производительность компиляции языка Go — это цель, определенная при первоначальной разработке языка Go.Перейти версии 1.4.3Пик достигнут, хотя он реализован на языке C, но, что более важно, он определяет модель построения языка для высокопроизводительного построения, что облегчает анализ зависимостей, избегая при этом повторного сканирования большого количества C/C++. заголовочные файлы. вместе сРеализация Go Bootstrap, используя язык go для реализации go Производительность компилятора значительно снизилась, но даже при этом его скорость компиляции по-прежнему остается одной из лучших среди основных языков программирования. после прохожденияGo 1.6прибытьGo1.9После того, как несколько версий оптимизировали компилятор, скорость компиляции go-компилятора былаВернуться примерно к 2/3 компилятора Go 1.4.3или более близкий уровень. существуетПерейти версии 1.9После введения параллельной компиляции представление команды Go об улучшении производительности инструмента немного изменилось: вместо того, чтобы вслепую выполнять оптимизацию производительности на уровне кода, они решили повторно использовать промежуточные результаты через Cache для достижения инкрементного построения для сокращения времени компиляции. взялся строить. Поэтому я думаю, что эта функцияОдно из самых больших изменений в Go 1.10.
1 Обзор
До Go 1.10 мы часто использовали go build -i для ускорения компиляции исходного кода проекта Go. Причина в том, что когда go build -i выполняется в первый раз, пакет, от которого зависит цель, будет установлен в $ GOPATH/pkg (файл .a), чтобы при последующем выполнении go build процесс сборки не перекомпилировал пакет зависимостей целевого файла, а напрямую связал пакет зависимостей, установленный при первом выполнении build -i, с добиться ускоренной компиляции! Взяв в качестве примера gocmpp/examples/client, вторая сборка занимает всего около четверти времени первой сборки:
➜ $GOPATH/src/github.com/bigwhite/gocmpp/examples/client git:(master) ✗ $time go build -i client.go
go build -i client.go 1.34s user 0.34s system 131% cpu 1.274 total
➜ $GOPATH/src/github.com/bigwhite/gocmpp/examples/client git:(master) ✗ $time go build -i client.go
go build -i client.go 0.38s user 0.16s system 116% cpu 0.465 total
Эти зависимые пакеты будут перекомпилированы только при изменении исходного файла зависимого пакета целевого файла (сравните время модификации исходного файла и время модификации файла .a в качестве основы для принятия решения о перекомпиляции или нет). и установлен. это немного похожеMakefileПринцип: инструмент make сравнивает дату модификации целевого файла и файла предварительных условий.Если дата файла предварительных требований новее, чем дата целевого файла, или цель не существует, то make выполнит впоследствии определенные команды.
Но даже в этом случае есть по крайней мере две проблемы, преследующие команду Го и большинство Гоферов:
-
Сравнения на основе временных меток не являются «разумными».
Когда содержимое исходного файла зависимого пакета объектного файла фактически не изменилось, но изменилось «время модификации», например, добавлена и сохранена строка, то эта строка удаляется и сохраняется. В таких случаях идеальным было бы установить зависимость без перекомпиляции, но текущий механизм go build -iПерекомпилируйте и установите этот пакет зависимостей. -
инкрементная сборкаНе "нормализованный"
В предыдущих версиях команда go build по умолчанию без параметров командной строки не устанавливала зависимые пакеты, поэтому каждый раз, когда выполнялась команда go build, исходный код зависимых пакетов перекомпилировался, а результаты помещались во временный каталог для финальной сборки. использование связи. Другими словами, наиболее часто используемая сборка go не реализует инкрементную компиляцию, и сообществу нужна нормализованная «инкрементная компиляция» для дальнейшего повышения эффективности.
Go 1.10 представил механизм кэширования для решения вышеуказанных проблем. Начиная с версии 1.10, инструмент сборки go будет поддерживать кеш результатов компиляции пакетов и некоторых метаданных, который находится в каталоге пользовательского кеша, указанном операционной системой по умолчанию, и данные используются для последующего повторного использования сборки; не только go build поддерживает «нормализацию». Для инкрементных сборок go test также поддерживает кэширование результатов тестирования при определенных условиях, тем самым ускоряя выполнение тестов.
b) go build with cache
Давайте интуитивно посмотрим на эффект сборки go 1.10.Первоначальный кеш пуст:
В качестве примера возьмем мой небольшой проект gocmpp, впервые создадим проект с помощью go 1.10:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $time go build
go build 1.22s user 0.43s system 175% cpu 0.939 total
Давайте построим его снова:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $time go build
go build 0.12s user 0.16s system 155% cpu 0.182 total
0,12 с против 1,22 с! Сборка через кеш сокращает время сборки на 1/10! Чтобы выяснить, что делает go build за кулисами, давайте очистим кеш (go clean -cache), а затем перестроим, на этот раз мы выведем подробный процесс сборки с помощью -v -x:
Подробный вывод для первой компиляции:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go build -x -v
WORK=/var/folders/2h/xr2tmnxx6qxc4w4w13m01fsh0000gn/T/go-build735203690
github.com/bigwhite/gocmpp/vendor/golang.org/x/text/encoding/internal/identifier
mkdir -p $WORK/b033/
cat >$WORK/b033/importcfg << 'EOF' # internal
# import config
EOF
cd $(GOPATH)/src/github.com/bigwhite/gocmpp/vendor/golang.org/x/text/encoding/internal/identifier
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/compile -o $WORK/b033/_pkg_.a -trimpath $WORK/b033 -p github.com/bigwhite/gocmpp/vendor/golang.org/x/text/encoding/internal/identifier -complete -buildid iZWJNg2FYmWoSCXb640o/iZWJNg2FYmWoSCXb640o -goversion go1.10rc2 -D "" -importcfg $WORK/b033/importcfg -pack -c=4 ./identifier.go ./mib.go
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/buildid -w $WORK/b033/_pkg_.a # internal
cp $WORK/b033/_pkg_.a /Users/tony/Library/Caches/go-build/14/14223040d851359359b0e531555a47e22f5dbd4bf434acc136a7c70c1fc3663f-d # internal
github.com/bigwhite/gocmpp/vendor/golang.org/x/text/transform
mkdir -p $WORK/b031/
cat >$WORK/b031/importcfg << 'EOF' # internal
# import config
packagefile bytes=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/bytes.a
packagefile errors=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/errors.a
packagefile io=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/io.a
packagefile unicode/utf8=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/unicode/utf8.a
EOF
.... ....
cd $(GOPATH)/src/github.com/bigwhite/gocmpp
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p github.com/bigwhite/gocmpp -complete -buildid 6LaoHtjkFhandbEhv7zD/6LaoHtjkFhandbEhv7zD -goversion go1.10rc2 -D "" -importcfg $WORK/b001/importcfg -pack -c=4 ./activetest.go ./client.go ./conn.go ./connect.go ./deliver.go ./fwd.go ./packet.go ./receipt.go ./server.go ./submit.go ./terminate.go
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /Users/tony/Library/Caches/go-build/e0/e02a5fec0835ca540b62053fdea82589e686e88bf48f18355ed38d41ad19f334-d # internal
Подробный вывод перекомпиляции:
$go build -x -v
WORK=/var/folders/2h/xr2tmnxx6qxc4w4w13m01fsh0000gn/T/go-build906548554
Давайте проанализируем это. При сборке в первый раз мы видим, что каждый пакет, от которого зависит gocmpp, и его собственный пакет будут скомпилированы и скопированы в каталог в /Users/tony/Library/Caches/go-build/, включая окончательный пакет gocmpp. это. Когда мы собираемся во второй раз, мы видим, что выводится только одна строка информации, потому что компилятор go находит скомпилированный кешированный результат, соответствующий пакету gocmpp в кеше, и фактическая компиляция не требуется.
Как упоминалось ранее, компилятор go 1.10 решает, следует ли перекомпилировать пакет, на основе содержимого, а не на основе сравнения временных меток. Изменим файл fwd.go в пакете gocmpp, удалим пустую строку, восстановим пустую строку, сохраним и выйдем. Давайте снова скомпилируем gocmpp:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go build -x -v
WORK=/var/folders/2h/xr2tmnxx6qxc4w4w13m01fsh0000gn/T/go-build857409409
Вы можете видеть, что компилятор go не перекомпилировал никаких пакетов. Если мы действительно изменили содержимое fwd.go, например удалив пустую строку, сохраните и скомпилируйте снова:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go build -x -v
WORK=/var/folders/2h/xr2tmnxx6qxc4w4w13m01fsh0000gn/T/go-build437927548
github.com/bigwhite/gocmpp
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile bytes=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/bytes.a
packagefile crypto/md5=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/crypto/md5.a
packagefile encoding/binary=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/encoding/binary.a
packagefile errors=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/errors.a
packagefile fmt=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/fmt.a
packagefile github.com/bigwhite/gocmpp/utils=/Users/tony/Test/GoToolsProjects/pkg/darwin_amd64/github.com/bigwhite/gocmpp/utils.a
packagefile io=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/io.a
packagefile log=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/log.a
packagefile net=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/net.a
packagefile os=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/os.a
packagefile strconv=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/strconv.a
packagefile strings=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/strings.a
packagefile sync=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/sync.a
packagefile sync/atomic=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/sync/atomic.a
packagefile time=/Users/tony/.bin/go1.10rc2/pkg/darwin_amd64/time.a
EOF
cd /Users/tony/Test/GoToolsProjects/src/github.com/bigwhite/gocmpp
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p github.com/bigwhite/gocmpp -complete -buildid trn5lvvRTk_UP3LcT5CC/trn5lvvRTk_UP3LcT5CC -goversion go1.10rc2 -D "" -importcfg $WORK/b001/importcfg -pack -c=4 ./activetest.go ./client.go ./conn.go ./connect.go ./deliver.go ./fwd.go ./packet.go ./receipt.go ./server.go ./submit.go ./terminate.go
/Users/tony/.bin/go1.10rc2/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /Users/tony/Library/Caches/go-build/7a/7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499-d # internal
Компилятор Go обнаружил изменения содержимого и перекомпилировал измененное содержимое пакета gocmpp.
c) Исследование каталога кеша
При добавлении механизма кэширования инструменты go добавили переменную GOCACHE и просмотр значения переменной через go env GOCACHE:
$go env GOCACHE
/Users/tony/Library/Caches/go-build
Если переменная окружения GOCACHE не сброшена, то по умолчанию в Linux GOCACHE="~/.cache/go-build", в Mac OS X GOCACHE="/Users/UserName/Library/Caches/go-build". В OS X мы входим в каталог $GOCACHE, и нас встречает:
➜ /Users/tony/Library/Caches/go-build $ls
00/ 18/ 30/ 48/ 60/ 78/ 90/ a7/ bf/ d7/ ef/
01/ 19/ 31/ 49/ 61/ 79/ 91/ a8/ c0/ d8/ f0/
02/ 1a/ 32/ 4a/ 62/ 7a/ 92/ a9/ c1/ d9/ f1/
03/ 1b/ 33/ 4b/ 63/ 7b/ 93/ aa/ c2/ da/ f2/
04/ 1c/ 34/ 4c/ 64/ 7c/ 94/ ab/ c3/ db/ f3/
05/ 1d/ 35/ 4d/ 65/ 7d/ 95/ ac/ c4/ dc/ f4/
06/ 1e/ 36/ 4e/ 66/ 7e/ 96/ ad/ c5/ dd/ f5/
07/ 1f/ 37/ 4f/ 67/ 7f/ 97/ ae/ c6/ de/ f6/
08/ 20/ 38/ 50/ 68/ 80/ 98/ af/ c7/ df/ f7/
09/ 21/ 39/ 51/ 69/ 81/ 99/ b0/ c8/ e0/ f8/
0a/ 22/ 3a/ 52/ 6a/ 82/ 9a/ b1/ c9/ e1/ f9/
0b/ 23/ 3b/ 53/ 6b/ 83/ 9b/ b2/ ca/ e2/ fa/
0c/ 24/ 3c/ 54/ 6c/ 84/ 9c/ b3/ cb/ e3/ fb/
0d/ 25/ 3d/ 55/ 6d/ 85/ 9d/ b4/ cc/ e4/ fc/
0e/ 26/ 3e/ 56/ 6e/ 86/ 9e/ b5/ cd/ e5/ fd/
0f/ 27/ 3f/ 57/ 6f/ 87/ 9f/ b6/ ce/ e6/ fe/
10/ 28/ 40/ 58/ 70/ 88/ README b7/ cf/ e7/ ff/
11/ 29/ 41/ 59/ 71/ 89/ a0/ b8/ d0/ e8/ log.txt
12/ 2a/ 42/ 5a/ 72/ 8a/ a1/ b9/ d1/ e9/ trim.txt
13/ 2b/ 43/ 5b/ 73/ 8b/ a2/ ba/ d2/ ea/
14/ 2c/ 44/ 5c/ 74/ 8c/ a3/ bb/ d3/ eb/
15/ 2d/ 45/ 5d/ 75/ 8d/ a4/ bc/ d4/ ec/
16/ 2e/ 46/ 5e/ 76/ 8e/ a5/ bd/ d5/ ed/
17/ 2f/ 47/ 5f/ 77/ 8f/ a6/ be/ d6/ ee/
Друзья, знакомые с принципом git, должны чувствовать, что эта структура организации каталогов знакома! Правильно, в каталоге ./git/object каждого проекта git мы также можем увидеть следующие результаты:
.git/objects git:(master) $ls
00/ 0c/ 18/ 24/ 30/ 3c/ 48/ 54/ 60/ 6c/ 78/ 84/ 90/ 9c/ a8/ b4/ c0/ cc/ d8/ e4/ f0/ fc/
01/ 0d/ 19/ 25/ 31/ 3d/ 49/ 55/ 61/ 6d/ 79/ 85/ 91/ 9d/ a9/ b5/ c1/ cd/ d9/ e5/ f1/ fd/
02/ 0e/ 1a/ 26/ 32/ 3e/ 4a/ 56/ 62/ 6e/ 7a/ 86/ 92/ 9e/ aa/ b6/ c2/ ce/ da/ e6/ f2/ fe/
03/ 0f/ 1b/ 27/ 33/ 3f/ 4b/ 57/ 63/ 6f/ 7b/ 87/ 93/ 9f/ ab/ b7/ c3/ cf/ db/ e7/ f3/ ff/
04/ 10/ 1c/ 28/ 34/ 40/ 4c/ 58/ 64/ 70/ 7c/ 88/ 94/ a0/ ac/ b8/ c4/ d0/ dc/ e8/ f4/ info/
05/ 11/ 1d/ 29/ 35/ 41/ 4d/ 59/ 65/ 71/ 7d/ 89/ 95/ a1/ ad/ b9/ c5/ d1/ dd/ e9/ f5/ pack/
06/ 12/ 1e/ 2a/ 36/ 42/ 4e/ 5a/ 66/ 72/ 7e/ 8a/ 96/ a2/ ae/ ba/ c6/ d2/ de/ ea/ f6/
07/ 13/ 1f/ 2b/ 37/ 43/ 4f/ 5b/ 67/ 73/ 7f/ 8b/ 97/ a3/ af/ bb/ c7/ d3/ df/ eb/ f7/
08/ 14/ 20/ 2c/ 38/ 44/ 50/ 5c/ 68/ 74/ 80/ 8c/ 98/ a4/ b0/ bc/ c8/ d4/ e0/ ec/ f8/
09/ 15/ 21/ 2d/ 39/ 45/ 51/ 5d/ 69/ 75/ 81/ 8d/ 99/ a5/ b1/ bd/ c9/ d5/ e1/ ed/ f9/
0a/ 16/ 22/ 2e/ 3a/ 46/ 52/ 5e/ 6a/ 76/ 82/ 8e/ 9a/ a6/ b2/ be/ ca/ d6/ e2/ ee/ fa/
0b/ 17/ 23/ 2f/ 3b/ 47/ 53/ 5f/ 6b/ 77/ 83/ 8f/ 9b/ a7/ b3/ bf/ cb/ d7/ e3/ ef/ fb/
Здесь предполагается, что go 1.10 должен использовать алгоритм дайджеста контента, такой как git, и режим хранения организации. В подробном выводе предыдущей сборки мы находим эту строку:
cp $WORK/b001/_pkg_.a /Users/tony/Library/Caches/go-build/7a/7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499-d # internal
Эта строка команды — скопировать пакет gocmpp в кеш, и мы идем в каталог 7a кеша, чтобы узнать:
➜ /Users/tony/Library/Caches/go-build/7a $tree
.
└── 7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499-d
0 directories, 1 file
Посмотрим на файл командой nm:
$go tool nm 7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499-d|more
1c319 T %22%22.(*Client).Connect
2e279 T %22%22.(*Client).Connect.func1
3fc22 R %22%22.(*Client).Connect.func1·f
1c79f T %22%22.(*Client).Disconnect
1c979 T %22%22.(*Client).RecvAndUnpackPkt
1c807 T %22%22.(*Client).SendReqPkt
1c8e2 T %22%22.(*Client).SendRspPkt
1e417 T %22%22.(*Cmpp2ConnRspPkt).Pack
... ...
Этот файл действительно является файлом gocmpp.a. Это также можно подтвердить, сравнив размер файла с размером файла после установки:
➜ /Users/tony/Library/Caches/go-build/7a $
-rw-r--r-- 1 tony staff 445856 Feb 15 22:34 7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499-d
vs.
➜ $GOPATH/pkg/darwin_amd64/github.com/bigwhite $ll
-rw-r--r-- 1 tony staff 445856 Feb 15 23:27 gocmpp.a
Другими словами, после того, как компилятор go получает значение дайджеста файла .a скомпилированного пакета, он сохраняет файл .a в каталоге $GOCACHE Имя этого каталога представляет собой первые две цифры значения дайджеста. (например, «7a» »), имя файла .a заменяется его дайджест-значением для последующего поиска и сравнения.
В каталоге кеша также есть важный файл: log.txt, который используется для записи журнала управления кешем, формат его содержимого следующий:
//log.txt
... ...
1518705271 get 7533a063cd8c37888b19674bf4a4bb7e25fa422041082566530d58538c031516
1518705271 miss b6b9f996fbd14e4fd43f72dc4f9082946cddd0d61d6c6143c88502c8a4001666
1518705271 put b6b9f996fbd14e4fd43f72dc4f9082946cddd0d61d6c6143c88502c8a4001666 7a5671578ed30b125257fd16d0f0b8ceaefd0acc3e44f082ffeecea9f1895499 445856
1518705271 put f5a641ca081a0d2d794b0b54aa9f89014dbb6ff8d14d26543846e1676eca4c21 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0
1518708456 get 899589360d856265a84825dbeb8d283ca84e12f154eefc12ba84870af13e1f63
1518708456 get 8a7fcd97a5f36bd00ef084856c63e4e2facedce33d19a5b557cc67f219787661
Целью этого файла журнала является помощь Russ Cox в отладке и диагностике проблем с кешем, который он разрабатывает. Конечно, если вы хорошо разбираетесь в механизме кеша, вы также можете позволить log.txt помочь вам диагностировать проблемы, связанные с кешем.
d) go test with cache
Версия go test версии 1.10 также поддерживает кеш, который кэширует результаты теста, выполненного go test. При этом в go 1.10 go test разделен на два режима выполнения: режим локального каталога и режим списка пакетов.В разных режимах вмешательство механизма кеша отличается.
режим локального каталога, то есть режим выполнения, в котором go test принимает весь текущий каталог в качестве неявного параметра, например, выполнение «go test» в определенном каталоге без каких-либо явных параметров списка пакетов после go test (конечно, другие можно использовать команды) параметр флага строки, например -v). В этом режиме механизм кэширования не вмешивается, а процесс выполнения go test такой же, как и до go 1.10. Взяв в качестве примера проект gocmpp, мы выполняем тест go в режиме локального каталога:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test
PASS
ok github.com/bigwhite/gocmpp 0.011s
Если задействован механизм кэширования, то в результатах выходного теста появится слово cached.Очевидно, что описанный выше процесс выполнения go-теста не использует тестовый кеш.
режим списка пакетов, то есть список пакетов явно передается после запуска теста, например: go test math, go test ., go test ./… и т. д. В этом режиме будет вмешиваться механизм тестового кэша. Два раза подряд выполняем go test в каталоге gocmpp:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test .
ok github.com/bigwhite/gocmpp 0.011s
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test .
ok github.com/bigwhite/gocmpp (cached)
Если вы хотите поближе взглянуть на подробный вывод выполнения теста go на этом этапе, вы можете выполнить go test -v .:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test -v .
=== RUN TestTypeString
--- PASS: TestTypeString (0.00s)
=== RUN TestCommandIdString
--- PASS: TestCommandIdString (0.00s)
=== RUN TestOpError
--- PASS: TestOpError (0.00s)
... ...
=== RUN TestCmppTerminateRspPktPack
--- PASS: TestCmppTerminateRspPktPack (0.00s)
=== RUN TestCmppTerminateRspUnpack
--- PASS: TestCmppTerminateRspUnpack (0.00s)
PASS
ok github.com/bigwhite/gocmpp 0.017s
Вы обнаружите, что на этот раз тест go не использует кеш. Если вы сделаете еще один go test -v .:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test -v .
=== RUN TestTypeString
--- PASS: TestTypeString (0.00s)
=== RUN TestCommandIdString
--- PASS: TestCommandIdString (0.00s)
=== RUN TestOpError
--- PASS: TestOpError (0.00s)
... ...
=== RUN TestCmppTerminateRspPktPack
--- PASS: TestCmppTerminateRspPktPack (0.00s)
=== RUN TestCmppTerminateRspUnpack
--- PASS: TestCmppTerminateRspUnpack (0.00s)
PASS
ok github.com/bigwhite/gocmpp (cached)
Тестовый кеш снова заработал. Похоже, что кеш не зависит от go test. и go test -v. Правильно, условия вмешательства для кеша go test, указанные в примечании к выпуску, следующие:
- Исполнитель и командная строка (и параметры) этого теста совпадают с предыдущим запуском теста (это объясняет, почему go test -v . не использует кеш, выполненный go test . );
- Файлы и переменные среды последнего выполнения теста на этот раз не изменились;
- Результат теста успешен;
- Запустите тесты как узел списка пакетов;
- Когда аргументы командной строки для тестирования используют подмножество "-cpu, -list, -parallel, -run, -short и -v"
Как мы видели ранее, результат вмешательства кэша в go test не будет показывать время, затраченное тестом, а вместо этого оно будет заменено словом (cached).
Большинству гоферов нравится тестировать кэш, но всегда бывают ситуации, когда кэш не приветствуется. На самом деле предыдущие условия четко подсказали сусликам, при каких условиях нельзя задействовать тестовый кеш.Идиоматический способ закрыть тестовый кешиспользовать -count=1:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test -count=1 -v .
=== RUN TestTypeString
--- PASS: TestTypeString (0.00s)
=== RUN TestCommandIdString
--- PASS: TestCommandIdString (0.00s)
=== RUN TestOpError
--- PASS: TestOpError (0.00s)
... ...
=== RUN TestCmppTerminateRspPktPack
--- PASS: TestCmppTerminateRspPktPack (0.00s)
=== RUN TestCmppTerminateRspUnpack
--- PASS: TestCmppTerminateRspUnpack (0.00s)
PASS
ok github.com/bigwhite/gocmpp 0.012s
Еще одно отличие go test в go 1.10 от предыдущих версий заключается в том, что go test автоматически выполняет go vet для тестируемого пакета перед фактическим выполнением теста, но этот vet выявляет только самые очевидные проблемы. И как только проблемы будут обнаружены, go test будет рассматривать эти проблемы как ошибки сборки, блокировать выполнение теста и позволять им появляться в тесте сбоя. Конечно, gopher может отключить эту предварительную ветеринарную проверку с помощью команды go test -vet=off.
4. pprof
Инструмент go pprof претерпел большие изменения: в него был добавлен веб-интерфейс, и в будущем его можно будет использовать для настройки программы Go с помощью графического метода вместе с go trace. Визуальный pprof очень прост в использовании.Давайте возьмем gocmpp в качестве примера, чтобы попробовать pprof из go 1.10.Сначала мы создаем файл профиля процессора:
➜ $GOPATH/src/github.com/bigwhite/gocmpp git:(master) ✗ $go test -run=^$ -bench=. -cpuprofile=profile.out
goos: darwin
goarch: amd64
pkg: github.com/bigwhite/gocmpp
BenchmarkRecvAndUnpackPkt-4 1000000 1534 ns/op
BenchmarkCmppConnReqPktPack-4 1000000 1398 ns/op
BenchmarkCmppConnReqPktUnpack-4 3000000 450 ns/op
BenchmarkCmpp2DeliverReqPktPack-4 1000000 1156 ns/op
BenchmarkCmpp2DeliverReqPktUnpack-4 3000000 567 ns/op
BenchmarkCmpp3DeliverReqPktPack-4 1000000 1173 ns/op
BenchmarkCmpp3DeliverReqPktUnpack-4 3000000 465 ns/op
BenchmarkCmpp2FwdReqPktPack-4 1000000 2079 ns/op
BenchmarkCmpp2FwdReqPktUnpack-4 1000000 1276 ns/op
BenchmarkCmpp3FwdReqPktPack-4 1000000 2507 ns/op
BenchmarkCmpp3FwdReqPktUnpack-4 1000000 1286 ns/op
BenchmarkCmpp2SubmitReqPktPack-4 1000000 1845 ns/op
BenchmarkCmpp2SubmitReqPktUnpack-4 1000000 1251 ns/op
BenchmarkCmpp3SubmitReqPktPack-4 1000000 1863 ns/op
BenchmarkCmpp3SubmitReqPktUnpack-4 2000000 656 ns/op
PASS
ok github.com/bigwhite/gocmpp 26.621s
Запустите веб-интерфейс pprof:
$go tool pprof -http=:8080 profile.out
pprof автоматически откроет браузер по умолчанию и перейдет на следующую страницу:
В меню просмотра мы можем видеть «сверху», «график», «заглянуть», «источник» и «разобрать» несколько параметров, эти параметры могут помочь вам переключаться между различными представлениями, начальным по умолчанию является представление графика. Однако в настоящее время в меню просмотра нет опции «Flame Graph».Чтобы использовать Flame Graph, нам нужно использовать собственный инструмент pprof, который можно получить с помощью go get -u github.com/google/pprof, после установки Native pprof появится в $GOROOT/bin.
Запустите веб-интерфейс с помощью собственного pprof:
$pprof -http=:8080 profile.out
Собственный pprof также автоматически откроет браузер и перейдет на следующую страницу:
Собственный веб-интерфейс pprof выглядит более совершенным, чем pprof в инструменте go 1.10, и самое большое отличие состоит в том, что пункт меню «Flame Graph» появляется в меню VIEW! Щелкаем по этому пункту меню, и перед нами представляется Flame Graph:
Как провести анализ флейм-графа здесь не основная задача, решайте сами. Дополнительные сведения о настройке производительности Go см.Руководство по диагностике предоставлено официальной компанией Go..
В-четвертых, стандартная библиотека
Как и в каждом предыдущем выпуске Go, изменения в стандартной библиотеке многочисленны и фрагментарны, и их нельзя здесь проиллюстрировать. И многие пакеты, затрагивающие "профессиональные области", такие как шифрование и дешифрование, требуют определенной степени профессиональной глубины, так что здесь лишь несколько "общих" изменений^0^.
1. strings.Builder
Пакет strings добавляет новый тип: Builder, который используется для замены bytes.Buffer в сценарии "написание строк". Из-за использования некоторых небезопасных технологий пакетов пользователь вызывает Builder.String(), чтобы вернуть окончательную написанную строку. ., позволяет избежать повторяющихся и ненужных копий памяти, повышает производительность обработки и оптимизирует выделение памяти. Давайте воспользуемся демонстрацией, чтобы увидеть преимущества Builder в этом сценарии:
//go1.10-examples/stdlib/stringsbuilder/builer.go
package builder
import (
"bytes"
"strings"
)
type BuilderByBytesBuffer struct {
b bytes.Buffer
}
func (b *BuilderByBytesBuffer) WriteString(s string) error {
_, err := b.b.WriteString(s)
return err
}
func (b *BuilderByBytesBuffer) String() string{
return b.b.String()
}
type BuilderByStringsBuilder struct {
b strings.Builder
}
func (b *BuilderByStringsBuilder) WriteString(s string) error {
_, err := b.b.WriteString(s)
return err
}
func (b *BuilderByStringsBuilder) String() string{
return b.b.String()
}
Исходные файлы тестов для сравнительного анализа BuilderByBytesBuffer и BuilderByStringsBuilder в приведенном выше коде выглядят следующим образом:
//go1.10-examples/stdlib/stringsbuilder/builer_test.go
package builder
import "testing"
func BenchmarkBuildStringWithBytesBuffer(b *testing.B) {
var builder BuilderByBytesBuffer
for i := 0; i < b.N; i++ {
builder.WriteString("Hello, ")
builder.WriteString("Go")
builder.WriteString("-1.10")
_ = builder.String()
}
}
func BenchmarkBuildStringWithStringsBuilder(b *testing.B) {
var builder BuilderByStringsBuilder
for i := 0; i < b.N; i++ {
builder.WriteString("Hello, ")
builder.WriteString("Go")
builder.WriteString("-1.10")
_ = builder.String()
}
}
Выполните тест, чтобы увидеть результаты:
$go test -bench . -benchmem
goos: darwin
goarch: amd64
pkg: github.com/bigwhite/experiments/go1.10-examples/stdlib/stringsbuilder
BenchmarkBuildStringWithBytesBuffer-4 100000 108471 ns/op 704073 B/op 1 allocs/op
BenchmarkBuildStringWithStringsBuilder-4 20000000 122 ns/op 80 B/op 0 allocs/op
PASS
ok github.com/bigwhite/experiments/go1.10-examples/stdlib/stringsbuilder 13.616s
Можно видеть, что StringsBuilder всесторонне сильнее, чем bytes.Buffer с точки зрения скорости обработки и оптимизации распределения Реальный пробел заключается в методе Builder.String.
2. пакет байтов
Несколько методов Fields, FieldsFunc, Split и SplitAfter пакета bytes изменились в базовой реализации, что изменило поведение внешнего дисплея, интуитивно почувствуем это на примере:
// go1.10-examples/stdlib/bytessplit/main.go
package main
import (
"bytes"
"fmt"
)
// 来自github.com/campoy/gotalks/blob/master/go1.10/bytes/fields.go
func desc(b []byte) string {
return fmt.Sprintf("len: %2d | cap: %2d | %q\n", len(b), cap(b), b)
}
func main() {
text := []byte("Hello, Go1.10 is coming!")
fmt.Printf("text: %s", desc(text))
subslices := bytes.Split(text, []byte(" "))
fmt.Printf("subslice 0: %s", desc(subslices[0]))
fmt.Printf("subslice 1: %s", desc(subslices[1]))
fmt.Printf("subslice 2: %s", desc(subslices[2]))
fmt.Printf("subslice 3: %s", desc(subslices[3]))
}
Давайте сначала скомпилируем и запустим демо с Go 1.9.2:
$go run main.go
text: len: 24 | cap: 32 | "Hello, Go1.10 is coming!"
subslice 0: len: 6 | cap: 32 | "Hello,"
subslice 1: len: 6 | cap: 25 | "Go1.10"
subslice 2: len: 2 | cap: 18 | "is"
subslice 3: len: 7 | cap: 15 | "coming!"
Давайте снова запустим демо с go 1.10rc2:
$go run main.go
text: len: 24 | cap: 32 | "Hello, Go1.10 is coming!"
subslice 0: len: 6 | cap: 6 | "Hello,"
subslice 1: len: 6 | cap: 6 | "Go1.10"
subslice 2: len: 2 | cap: 2 | "is"
subslice 3: len: 7 | cap: 15 | "coming!"
Сравнив столбец ограничения в двух выходных результатах, вы обнаружите, что в результатах, выводимых командой go 1.10Значения len и cap каждого подслайса (кроме последнего) равны, вместо того, чтобы использовать оставшиеся заглавные буквы исходного среза в качестве заглавных букв подслоя. Это изменение поведения сделано из соображений безопасности, предотвращая влияние модификаций подслоев, совместно использующих базовый слой, на соседние подслои, что ограничивает их пропускную способность.
В конкретной реализации методов Fields, FieldsFunc, Split и SplitAfter Go 1.10 использует то, что мы обычно не используем».Full slice expression", т.е.: a[low, high, max], чтобы указать шапку подслайса.
5. Производительность
Для статически компилируемого языка типов Go производительность всегда была ключевой целью разработки, и почти каждая версия Go, выпущенная за последние два года, преподносила Gophers сюрпризы. Когда дело доходит до производительности Go, Gopher обычно заботятся о следующих аспектах:
1. Производительность компиляции
Производительность компиляции Go 1.10 Как мы уже говорили, самым большим изменением является реализация механизма кэширования. Факты доказали, что использование механизма кэширования значительно повысит эффективность вашей работы в ежедневном процессе разработки, и чем больше проект, тем больше.
2. Производительность целевого кода
На протяжении многих лет команда Go постоянно оптимизировала производительность объектного кода, сгенерированного компилятором, например, вПерейти версии 1.7Представлен в бэкенде ssa. В Go 1.10 продолжается дальнейшая оптимизация генерации объектного кода, хотя это гораздо меньший шаг, чем введение ssa.
3. Производительность ГХ
Производительность GC всегда была проблемой для большинства Gophers.Go 1.10 проделал большую работу по уменьшению задержки выделения памяти и бремени времени выполнения GC, но в целом Go 1.10 не представил легендарногоTOC(Transaction Oritented Collector), так что макроскопически изменения GC не очень велики. «Эксперты» по тестированию производительности GC в ТвиттереBrian Hatfieldв движении 1.10rc1ГХ тестПозже также было заявлено, что изменения не очень значительны по сравнению с Go 1.9.
6. Резюме
Go версии 1.10 — это еще один результат совместных усилий команды Go и сообщества Gopher, так что Gopher во всем мире сохраняют большой энтузиазм и надежды на Go. Конечно, в Go 1.10 есть еще много изменений, таких как:
- Поддержка спецификации Unicode была обновлена до10.0;
- На разных платформах ассемблер поддерживает более высокопроизводительные инструкции;
- плагин поддерживает darwin/amd64 и т.д.;
- gofmt и go doc дополнительно оптимизируют формат вывода и улучшают опыт разработчиков gopher;
- cgo поддерживает передачу строк go непосредственно в код C;
…
очень много! Из-за нехватки места здесь это не может быть объяснено подробно. прочитатьGo 1.10 Release Noteэто то, что должен делать каждый суслик.
Вышеупомянутая проверка проверена на mac OS X, go 1.10rc2, а исходный код демо можно найти вСкачать здесь.
7. Ссылки
- Go 1.10 Release Notes
- The State of Go by campoy
- Go 1.10
- pprof user interface
- cmd/go content-based staleness submitted
- Go 1.10 cmd/go: build cache, test cache, go install, go vet, test vet
Известный поставщик услуг облачного хостинга DigitalOcean выпустил последний план хостинга.Конфигурация Droplet начального уровня обновлена до: 1 ядро ЦП, 1 ГБ памяти, 25 ГБ высокоскоростной SSD, а цена составляет 5 долларов США в месяц. Друзья, которым нужно использовать DigitalOcean, могут открыть этоадрес ссылки: https://m.do.co/c/bff6eed92687 Начните свой путь хостинга DO.
моя контактная информация:
Weibo: http://weibo.com/bigwhite20xx
Публичный аккаунт WeChat: iamtonybai
Блог: tonybai.com
github: https://github.com/bigwhite
WeChat ценит:
Способы делового сотрудничества: написание книг, издание книг, обучение, онлайн-курсы, партнерское предпринимательство, консалтинг, рекламное сотрудничество.
© 2018, bigwhite. все права защищены.
Related posts: