Deep Engineering

MEASUREMENT

bench/gointerface/escape.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/interfaces

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

43 lines
#!/usr/bin/env bash
#
# Упаковка в интерфейс: что решает тип и что решает escape analysis.
#
# ЗАЧЕМ СКРИПТ. Раздел «ВИД ХРАНЕНИЯ РЕШАЕТ ТИП, ВЫДЕЛЕНИЕ — ESCAPE ANALYSIS»
# в internals.go считает выделения через testing.AllocsPerRun. Это ответ на
# «сколько», но не на «почему». Почему — говорит компилятор: с -gcflags=-m он
# печатает для каждой упаковки, убегает ли копия значения в кучу. Скрипт
# ставит оба вывода рядом, по одним и тем же строкам исходника.
#
# Появился 02.11.2026 в ответ на замечание аудита GO-I01: правило «не указатель
# — значит выделение в куче» ложно на go1.24.7 в обе стороны.
#
# ЗАПУСК:
#
#	bash bench/gointerface/escape.sh
set -u

cd "$(dirname "$0")/../.."
src=bench/gointerface/internals.go

go run "$src" escape

echo
echo "=== РЕШЕНИЯ КОМПИЛЯТОРА: go build -gcflags=-m, строки четырёх случаев ==="
for fn in boxLocalStruct boxEscapingStruct boxPtrField boxIntField; do
  line="$(grep -n "^func $fn()" "$src" | cut -d: -f1)"
  msgs="$(go build -gcflags=-m -o /dev/null "$src" 2>&1 \
    | grep -E "^$src:$line:[0-9]+: " | grep -v "can inline" | sed "s|^$src:||")"
  printf '  %-18s %s\n' "$fn" "$(grep "^func $fn()" "$src" | sed 's/^func [A-Za-z]*() *//')"
  if [ -n "$msgs" ]; then
    printf '%s\n' "$msgs" | sed 's/^/      /'
  else
    echo "      (сообщений об упаковке нет: копии нет, значение хранится прямо)"
  fi
done

echo
echo "  «does not escape» — копия для интерфейса размещена на стеке, отсюда 0."
echo "  «escapes to heap» — копия убегает, отсюда mallocgc и 1 выделение."
echo "  Для Handle компилятору нечего размещать: тип хранится в интерфейсе"
echo "  прямо (types.IsDirectIface), второе слово — сам указатель из поля."