Deep Engineering

MEASUREMENT

bench/goescape/decisions.sh

The script that produced the numbers in the article, and the record of the run. The file is read from the repository at build time — this is the code that was run, not a copy of it.

Cited in
/en/interview/golang/escape-analysis

The run below is recorded in Russian. It is a lab record, kept in the language it was written in; the numbers, the tables and the code read the same either way.

Record of the run

This measurement has no recorded run — only the script.

Script

39 lines
#!/usr/bin/env bash
#
# Решения escape-анализа, напечатанные самим компилятором.
#
# ЗАЧЕМ ОТДЕЛЬНЫЙ СКРИПТ. Число выделений (`testing.AllocsPerRun`) отвечает на
# вопрос «сколько», но не на вопрос «почему именно это». Флаг `-m` заставляет
# компилятор назвать своё решение по каждому значению — и это единственный
# способ проверить объяснение, а не поверить ему.
#
# ПОЧЕМУ -l. Без него компилятор встраивает мелкие функции, и решения
# печатаются про тела, которых в итоговом коде уже нет. С `-l` строки отчёта
# соответствуют исходнику один к одному.
#
# ПОЧЕМУ ВЫВОД ФИЛЬТРУЕТСЯ. Полный отчёт содержит десятки строк про
# внутренности `testing` и `fmt` — они верны, но к уроку отношения не имеют.
# Оставлены только строки про четыре функции задачи 1, то есть ровно те, чьи
# числа урок и объясняет.
#
# ЗАПУСК:
#
#	bash bench/goescape/decisions.sh
set -u

cd "$(dirname "$0")"

echo "go build -gcflags='-m -l' | решения компилятора"
echo

# Диапазон строк задачи 1: от объявления local() до конца intoInterface().
go run -gcflags='-m -l' practice.go 2>&1 |
	grep -E '^\./practice\.go:(3[6-9]|4[0-9]|5[0-8]):' |
	grep -E 'escape|moved to heap'

echo
echo "  Читается так: «does not escape» — значение осталось в кадре,"
echo "  «escapes to heap» — обязано его пережить. Обратите внимание на"
echo "  первую строку: там взят АДРЕС локальной структуры, и компилятор"
echo "  всё равно оставил её на стеке."