The Go Blog
Отладка того, что вы разворачиваете в Go 1.12
Введение
Go 1.11 и Go 1.12 обеспечивают значительный прогресс в возможности отладки тех же оптимизированных бинарных файлов, которые разворачиваются в продакшене.
По мере того как компилятор Go становился всё более агрессивным в генерации более быстрых бинарных файлов, мы потеряли в отладочности. В Go 1.10 пользователям приходилось полностью отключать оптимизации, чтобы получить хорошее взаимодействие с инструментами отладки, такими как Delve. Но пользователи не должны были жертвовать производительностью ради отладочности, особенно при запуске сервисов в продакшене. Если ваша проблема возникает в продакшене, вам нужно отлаживать её в продакшене, и это не должно требовать разворачивания неоптимизированных бинарных файлов.
Для Go 1.11 и 1.12 мы сосредоточились на улучшении процесса отладки оптимизированных бинарных файлов (по умолчанию компилятор Go использует оптимизации). Улучшения включают
- Более точное рассмотрение значений, особенно аргументов при входе в функцию;
- Более точное определение границ инструкций, благодаря чему шаги становятся менее резкими, а точки останова чаще попадают туда, где ожидает программист;
- И предварительную поддержку Delve для вызова функций Go (горутины и сборка мусора делают это сложнее, чем в C и C++).
Отладка оптимизированного кода с помощью Delve
Delve — это отладчик для Go на x86, поддерживающий как Linux, так и macOS. Delve осведомлена о горутинах и других особенностях Go и предоставляет один из лучших способов отладки Go-кода. Delve также является движком отладки в GoLand, VS Code, и Vim.
Delve обычно пересобирает код, который она отлаживает с помощью -gcflags "all=-N -l",
что отключает инлайнинг и большинство оптимизаций.
Чтобы отладить оптимизированный код с помощью delve, сначала соберите оптимизированный бинарный файл,
затем используйте dlv exec your_program для его отладки.
Или, если у вас есть файл core из сбоя,
вы можете проанализировать его с помощью dlv core your_program your_core.
С Go 1.12 и последними версиями Delve вы должны быть способны исследовать множество переменных,
даже в оптимизированных бинарных файлах.
Улучшенное рассмотрение значений
При отладке оптимизированных бинарных файлов, созданных с помощью Go 1.10, значения переменных обычно были полностью недоступны. Напротив, начиная с Go 1.11, переменные можно обычно исследовать даже в оптимизированных бинарных файлах, если они не были полностью оптимизированы. В Go 1.11 компилятор начал генерировать DWARF location lists, благодаря которым отладчики могут отслеживать переменные по мере их перемещения в и из регистров и восстанавливать сложные объекты, разбитые на разные регистры и слоты стека.
Улучшенное пошаговое выполнение
На этом рисунке показан пример пошагового выполнения простой функции в отладчике в Go 1.10 с выделенными красными стрелками ошибками (пропущенные и повторяющиеся строки).
Такие ошибки легко сбивают с толку при пошаговом выполнении программы и мешают установке точек останова.
Go 1.11 и Go 1.12 записывают информацию о границах инструкций и лучше отслеживают номера строк исходного кода при оптимизациях и встраивании (inlining). В результате, в Go 1.12 пошаговое выполнение этого кода останавливается на каждой строке и делает это в ожидаемом порядке.
Вызовы функций
Поддержка вызовов функций в Delve всё ещё находится в стадии разработки, но простые случаи уже работают. Например:
<code>(dlv) call fib(6) > main.main() ./hello.go:15 (PC: 0x49d648) Values returned: ~r1: 8 </code>
Путь вперёд
Go 1.12 — это шаг к лучшему опыту отладки оптимизированных бинарных файлов, и у нас есть планы по дальнейшему улучшению.
Существуют фундаментальные компромиссы между возможностью отладки и производительностью, поэтому мы сосредотачиваемся на устранении наиболее критичных проблем отладки и работаем над сбором автоматических метрик для мониторинга прогресса и выявления регрессий.
Мы сосредоточены на генерации корректной информации для отладчиков о местоположении переменных, поэтому если переменная может быть напечатана, она выводится корректно. Также мы рассматриваем возможность сделать значения переменных доступными чаще, особенно в ключевых точках, таких как места вызовов функций, хотя в большинстве случаев улучшение этого требует замедления выполнения программы. Наконец, мы работаем над улучшением пошагового выполнения: фокусируемся на правильном порядке выполнения при паниках, порядке выполнения вокруг циклов и, в целом, на следовании исходному порядку, где это возможно.
Примечание о поддержке macOS
Go 1.11 начал сжимать отладочную информацию для уменьшения размера бинарных файлов.
Это нативно поддерживается Delve, но ни LLDB, ни GDB не поддерживают сжатую отладочную информацию на macOS.
Если вы используете LLDB или GDB, существуют два обходных пути:
соберите бинарные файлы с флагом -ldflags=-compressdwarf=false,
или используйте splitdwarf
(go get golang.org/x/tools/cmd/splitdwarf) для распаковки отладочной информации
в существующем бинарном файле.
Следующая статья: Результаты опроса Go 2018
Предыдущая статья: Использование Go Modules
Индекс блога