|
|
<!DOCTYPE html>
|
|
|
<html lang="zh-cn" dir="ltr">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<meta name="description" content="Go 内置分析工具 # 这一章节将介绍Go 内置分析工具。通过这些工具我们可以分析、诊断、跟踪竞态,GMP调度,CPU耗用等问题。
|
|
|
go build # go build命令用来编译Go 程序。go build重要的命令行选项有以下几个:
|
|
|
go build -n # -n选项用来显示编译过程中所有执行的命令,不会真正执行。通过该选项我们可以查看编译器,连接器如何工作的:
|
|
|
# # _/home/vagrant/dive-into-go # mkdir -p $WORK/b001/ cat >$WORK/b001/importcfg << 'EOF' # internal # import config packagefile fmt=/usr/lib/go/pkg/linux_amd64/fmt.a packagefile runtime=/usr/lib/go/pkg/linux_amd64/runtime.a EOF cd /home/vagrant/dive-into-go /usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid RcHLBQbXBa2gQVsMR6P0/RcHLBQbXBa2gQVsMR6P0 -goversion go1.14.13 -D _/home/vagrant/dive-into-go -importcfg $WORK/b001/importcfg -pack ./empty_string.go ./string.go /usr/lib/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/_pkg_.a # internal cat >$WORK/b001/importcfg.link << 'EOF' # internal packagefile _/home/vagrant/dive-into-go=$WORK/b001/_pkg_.">
|
|
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
|
|
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#343a40">
|
|
|
<meta name="color-scheme" content="light dark"><meta property="og:title" content="Go语言内置分析工具" />
|
|
|
<meta property="og:description" content="Go 内置分析工具 # 这一章节将介绍Go 内置分析工具。通过这些工具我们可以分析、诊断、跟踪竞态,GMP调度,CPU耗用等问题。
|
|
|
go build # go build命令用来编译Go 程序。go build重要的命令行选项有以下几个:
|
|
|
go build -n # -n选项用来显示编译过程中所有执行的命令,不会真正执行。通过该选项我们可以查看编译器,连接器如何工作的:
|
|
|
# # _/home/vagrant/dive-into-go # mkdir -p $WORK/b001/ cat >$WORK/b001/importcfg << 'EOF' # internal # import config packagefile fmt=/usr/lib/go/pkg/linux_amd64/fmt.a packagefile runtime=/usr/lib/go/pkg/linux_amd64/runtime.a EOF cd /home/vagrant/dive-into-go /usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid RcHLBQbXBa2gQVsMR6P0/RcHLBQbXBa2gQVsMR6P0 -goversion go1.14.13 -D _/home/vagrant/dive-into-go -importcfg $WORK/b001/importcfg -pack ./empty_string.go ./string.go /usr/lib/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/_pkg_.a # internal cat >$WORK/b001/importcfg.link << 'EOF' # internal packagefile _/home/vagrant/dive-into-go=$WORK/b001/_pkg_." />
|
|
|
<meta property="og:type" content="article" />
|
|
|
<meta property="og:url" content="https://go.cyub.vip/analysis-tools/go-buildin-tools/" /><meta property="article:section" content="analysis-tools" />
|
|
|
|
|
|
|
|
|
<title>Go语言内置分析工具 | 深入Go语言之旅</title>
|
|
|
<link rel="manifest" href="/manifest.json">
|
|
|
<link rel="icon" href="/favicon.png" >
|
|
|
<link rel="stylesheet" href="/book.min.f06572240ce28e67eb332ac5cf5d59a696c47ad4c6f700d5842c5ed93dd8ec77.css" integrity="sha256-8GVyJAzijmfrMyrFz11ZppbEetTG9wDVhCxe2T3Y7Hc=" crossorigin="anonymous">
|
|
|
<script defer src="/flexsearch.min.js"></script>
|
|
|
<script defer src="/en.search.min.93e09a692e83129c8b0cc95c521eab7d4f5256b35651cf852c4ad4185bdc55a5.js" integrity="sha256-k+CaaS6DEpyLDMlcUh6rfU9SVrNWUc+FLErUGFvcVaU=" crossorigin="anonymous"></script>
|
|
|
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BQ229RRTTX"></script>
|
|
|
<script>
|
|
|
var doNotTrack = false;
|
|
|
if (!doNotTrack) {
|
|
|
window.dataLayer = window.dataLayer || [];
|
|
|
function gtag(){dataLayer.push(arguments);}
|
|
|
gtag('js', new Date());
|
|
|
gtag('config', 'G-BQ229RRTTX', { 'anonymize_ip': false });
|
|
|
}
|
|
|
</script>
|
|
|
<!--
|
|
|
Made with Book Theme
|
|
|
https://github.com/alex-shpak/hugo-book
|
|
|
-->
|
|
|
|
|
|
</head>
|
|
|
<body dir="ltr">
|
|
|
<input type="checkbox" class="hidden toggle" id="menu-control" />
|
|
|
<input type="checkbox" class="hidden toggle" id="toc-control" />
|
|
|
<main class="container flex">
|
|
|
<aside class="book-menu">
|
|
|
<div class="book-menu-content">
|
|
|
|
|
|
<nav>
|
|
|
<h2 class="book-brand">
|
|
|
<a class="flex align-center" href="/"><img src="https://static.cyub.vip/images/202310/golang-480.png" alt="Logo" /><span>深入Go语言之旅</span>
|
|
|
</a>
|
|
|
</h2>
|
|
|
|
|
|
|
|
|
<div class="book-search">
|
|
|
<input type="text" id="book-search-input" placeholder="Search" aria-label="Search" maxlength="64" data-hotkeys="s/" />
|
|
|
<div class="book-search-spinner hidden"></div>
|
|
|
<ul id="book-search-results"></ul>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
|
<li>
|
|
|
<a href="https://www.cyub.vip/" target="_blank" rel="noopener">
|
|
|
个人博客
|
|
|
</a>
|
|
|
</li>
|
|
|
|
|
|
<li>
|
|
|
<a href="https://github.com/cyub" target="_blank" rel="noopener">
|
|
|
Github主页
|
|
|
</a>
|
|
|
</li>
|
|
|
|
|
|
<li>
|
|
|
<a href="https://www.topgoer.cn/?ref=go.cyub.vip" target="_blank" rel="noopener">
|
|
|
地鼠文档
|
|
|
</a>
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
<li>
|
|
|
<p><strong>
|
|
|
<a href="/">深入Go语言之旅</a></strong></p>
|
|
|
</li>
|
|
|
<li>
|
|
|
<p><strong>准备篇</strong></p>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/compiler/">编译流程</a></li>
|
|
|
<li>
|
|
|
<a href="/analysis-tools/">分析工具</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/analysis-tools/gdb/">GDB</a></li>
|
|
|
<li>
|
|
|
<a href="/analysis-tools/dlv/">Delve</a></li>
|
|
|
<li>
|
|
|
<a href="/analysis-tools/go-buildin-tools/"class=active>Go 内置工具</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/go-assembly/">Go汇编</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<p><strong>基础篇</strong></p>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/type/">数据类型与数据结构</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/type/string/">字符串</a></li>
|
|
|
<li>
|
|
|
<a href="/type/array/">数组</a></li>
|
|
|
<li>
|
|
|
<a href="/type/slice/">切片</a></li>
|
|
|
<li>
|
|
|
<a href="/type/nil/">nil</a></li>
|
|
|
<li>
|
|
|
<a href="/type/empty_struct/">空结构体</a></li>
|
|
|
<li>
|
|
|
<a href="/type/pointer/">指针</a></li>
|
|
|
<li>
|
|
|
<a href="/type/map/">映射</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/function/">函数</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/function/first-class/">一等公民</a></li>
|
|
|
<li>
|
|
|
<a href="/function/call-stack/">函数调用栈</a></li>
|
|
|
<li>
|
|
|
<a href="/function/pass-by-value/">值传递</a></li>
|
|
|
<li>
|
|
|
<a href="/function/closure/">闭包</a></li>
|
|
|
<li>
|
|
|
<a href="/function/method/">方法</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/feature/">语言特性</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/feature/comma-ok/">逗号ok模式</a></li>
|
|
|
<li>
|
|
|
<a href="/feature/for-range/">遍历 - for-range语法</a></li>
|
|
|
<li>
|
|
|
<a href="/feature/defer/">延迟执行 - defer语法</a></li>
|
|
|
<li>
|
|
|
<a href="/feature/select/">通道选择器 - select语法</a></li>
|
|
|
<li>
|
|
|
<a href="/feature/panic-recover/">恐慌与恢复 - panic/recover</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<p><strong>运行时篇</strong></p>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/concurrency/">并发编程</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/concurrency/memory-model/">内存模型</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/context/">上下文 - context</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/channel/">通道 - channel</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/atomic/">原子操作 - atomic</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-map/">并发Map - sync.Map</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-waitgroup/">等待组 - sync.WaitGroup</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-once/">一次性操作 - sync.Once</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-pool/">缓冲池 - sync.Pool</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-cond/">条件变量 - sync.Cond</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-mutex/">互斥锁 - sync.Mutex</a></li>
|
|
|
<li>
|
|
|
<a href="/concurrency/sync-rwmutex/">读写锁 - sync.RWMutex</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/gmp/">G-M-P调度机制</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/gmp/gmp-model/">调度机制概述</a></li>
|
|
|
<li>
|
|
|
<a href="/gmp/scheduler/">调度器</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/memory/">内存管理</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/memory/allocator/">内存分配器</a></li>
|
|
|
<li>
|
|
|
<a href="/memory/gc/">GC</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li>
|
|
|
<a href="/type-system/">类型系统</a>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="/type-system/type/">类型系统</a></li>
|
|
|
<li>
|
|
|
<a href="/type-system/interface/">接口</a></li>
|
|
|
<li>
|
|
|
<a href="/type-system/reflect/">反射</a></li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
</aside>
|
|
|
|
|
|
<div class="book-page">
|
|
|
<header class="book-header">
|
|
|
|
|
|
<div class="flex align-center justify-between">
|
|
|
<label for="menu-control">
|
|
|
<img src="/svg/menu.svg" class="book-icon" alt="Menu" />
|
|
|
</label>
|
|
|
|
|
|
<strong>Go语言内置分析工具</strong>
|
|
|
|
|
|
<label for="toc-control">
|
|
|
|
|
|
</label>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
<article class="markdown"><h1 id="go-内置分析工具">
|
|
|
Go 内置分析工具
|
|
|
<a class="anchor" href="#go-%e5%86%85%e7%bd%ae%e5%88%86%e6%9e%90%e5%b7%a5%e5%85%b7">#</a>
|
|
|
</h1>
|
|
|
<p>这一章节将介绍Go 内置分析工具。通过这些工具我们可以分析、诊断、跟踪竞态,GMP调度,CPU耗用等问题。</p>
|
|
|
<h2 id="go-build">
|
|
|
go build
|
|
|
<a class="anchor" href="#go-build">#</a>
|
|
|
</h2>
|
|
|
<p><code>go build</code>命令用来编译Go 程序。<code>go build</code>重要的命令行选项有以下几个:</p>
|
|
|
<h3 id="go-build--n">
|
|
|
go build -n
|
|
|
<a class="anchor" href="#go-build--n">#</a>
|
|
|
</h3>
|
|
|
<p><code>-n</code>选项用来显示编译过程中所有执行的命令,不会真正执行。通过该选项我们可以查看编译器,连接器如何工作的:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e">#</span>
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e"># _/home/vagrant/dive-into-go</span>
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span>mkdir -p $WORK/b001/
|
|
|
</span></span><span style="display:flex;"><span>cat >$WORK/b001/importcfg <span style="color:#e6db74"><< 'EOF' # internal
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"># import config
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile fmt=/usr/lib/go/pkg/linux_amd64/fmt.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile runtime=/usr/lib/go/pkg/linux_amd64/runtime.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
|
|
|
</span></span><span style="display:flex;"><span>cd /home/vagrant/dive-into-go
|
|
|
</span></span><span style="display:flex;"><span>/usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/b001/_pkg_.a -trimpath <span style="color:#e6db74">"</span>$WORK<span style="color:#e6db74">/b001=>"</span> -p main -complete -buildid RcHLBQbXBa2gQVsMR6P0/RcHLBQbXBa2gQVsMR6P0 -goversion go1.14.13 -D _/home/vagrant/dive-into-go -importcfg $WORK/b001/importcfg -pack ./empty_string.go ./string.go
|
|
|
</span></span><span style="display:flex;"><span>/usr/lib/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/_pkg_.a <span style="color:#75715e"># internal</span>
|
|
|
</span></span><span style="display:flex;"><span>cat >$WORK/b001/importcfg.link <span style="color:#e6db74"><< 'EOF' # internal
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile _/home/vagrant/dive-into-go=$WORK/b001/_pkg_.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile fmt=/usr/lib/go/pkg/linux_amd64/fmt.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile runtime=/usr/lib/go/pkg/linux_amd64/runtime.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile errors=/usr/lib/go/pkg/linux_amd64/errors.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/fmtsort=/usr/lib/go/pkg/linux_amd64/internal/fmtsort.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile io=/usr/lib/go/pkg/linux_amd64/io.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile math=/usr/lib/go/pkg/linux_amd64/math.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile os=/usr/lib/go/pkg/linux_amd64/os.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile reflect=/usr/lib/go/pkg/linux_amd64/reflect.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile strconv=/usr/lib/go/pkg/linux_amd64/strconv.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile sync=/usr/lib/go/pkg/linux_amd64/sync.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile unicode/utf8=/usr/lib/go/pkg/linux_amd64/unicode/utf8.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/bytealg=/usr/lib/go/pkg/linux_amd64/internal/bytealg.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/cpu=/usr/lib/go/pkg/linux_amd64/internal/cpu.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile runtime/internal/atomic=/usr/lib/go/pkg/linux_amd64/runtime/internal/atomic.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile runtime/internal/math=/usr/lib/go/pkg/linux_amd64/runtime/internal/math.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile runtime/internal/sys=/usr/lib/go/pkg/linux_amd64/runtime/internal/sys.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/reflectlite=/usr/lib/go/pkg/linux_amd64/internal/reflectlite.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile sort=/usr/lib/go/pkg/linux_amd64/sort.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile math/bits=/usr/lib/go/pkg/linux_amd64/math/bits.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/oserror=/usr/lib/go/pkg/linux_amd64/internal/oserror.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/poll=/usr/lib/go/pkg/linux_amd64/internal/poll.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/syscall/execenv=/usr/lib/go/pkg/linux_amd64/internal/syscall/execenv.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/syscall/unix=/usr/lib/go/pkg/linux_amd64/internal/syscall/unix.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/testlog=/usr/lib/go/pkg/linux_amd64/internal/testlog.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile sync/atomic=/usr/lib/go/pkg/linux_amd64/sync/atomic.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile syscall=/usr/lib/go/pkg/linux_amd64/syscall.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile time=/usr/lib/go/pkg/linux_amd64/time.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile unicode=/usr/lib/go/pkg/linux_amd64/unicode.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">packagefile internal/race=/usr/lib/go/pkg/linux_amd64/internal/race.a
|
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
|
|
|
</span></span><span style="display:flex;"><span>mkdir -p $WORK/b001/exe/
|
|
|
</span></span><span style="display:flex;"><span>cd .
|
|
|
</span></span><span style="display:flex;"><span>/usr/lib/go/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode<span style="color:#f92672">=</span>exe -buildid<span style="color:#f92672">=</span>nR64Q3qx-0ZdNI4_-qJS/RcHLBQbXBa2gQVsMR6P0/RcHLBQbXBa2gQVsMR6P0/nR64Q3qx-0ZdNI4_-qJS -extld<span style="color:#f92672">=</span>gcc $WORK/b001/_pkg_.a
|
|
|
</span></span><span style="display:flex;"><span>/usr/lib/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/exe/a.out <span style="color:#75715e"># internal</span>
|
|
|
</span></span><span style="display:flex;"><span>mv $WORK/b001/exe/a.out dive-into-go
|
|
|
</span></span></code></pre></div><h3 id="go-build--race">
|
|
|
go build -race
|
|
|
<a class="anchor" href="#go-build--race">#</a>
|
|
|
</h3>
|
|
|
<p><code>-race</code>选项用来检查代码中是否存在竞态问题。<code>-race</code>可以用在多个子命令中:</p>
|
|
|
<pre tabindex="0"><code>go test -race mypkg
|
|
|
go run -race mysrc.go
|
|
|
go build -race mycmd
|
|
|
go install -race mypkg
|
|
|
</code></pre><p>下面是来自Go语言官方博客的一个示例<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>,在该示例中演示了使用<code>-race</code>选项检查代码中的竞态问题:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">start</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>()
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">t</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Timer</span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">t</span> = <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">AfterFunc</span>(<span style="color:#a6e22e">randomDuration</span>(), <span style="color:#66d9ef">func</span>() {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>().<span style="color:#a6e22e">Sub</span>(<span style="color:#a6e22e">start</span>))
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Reset</span>(<span style="color:#a6e22e">randomDuration</span>())
|
|
|
</span></span><span style="display:flex;"><span> })
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Sleep</span>(<span style="color:#ae81ff">5</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>)
|
|
|
</span></span><span style="display:flex;"><span>}
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">randomDuration</span>() <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Duration</span> {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Duration</span>(<span style="color:#a6e22e">rand</span>.<span style="color:#a6e22e">Int63n</span>(<span style="color:#ae81ff">1e9</span>))
|
|
|
</span></span><span style="display:flex;"><span>}
|
|
|
</span></span></code></pre></div><p>上面代码完成的功能是通过<code>time.AfterFunc</code>创建定时器,该定时器会在<code>randomDuration()</code>时候打印消息,此外还会通过<code>Rest()</code>方法重置该定时器,以达到重复利用该定时器目的。</p>
|
|
|
<p>当我们使用<code>-race</code>选项执行检查时候,可以发现上面代码是存在竞态问题的:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ go run -race main.go
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">==================</span>
|
|
|
</span></span><span style="display:flex;"><span>WARNING: DATA RACE
|
|
|
</span></span><span style="display:flex;"><span>Read by goroutine 5:
|
|
|
</span></span><span style="display:flex;"><span> main.func·001<span style="color:#f92672">()</span>
|
|
|
</span></span><span style="display:flex;"><span> race.go:14 +0x169
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span>Previous write by goroutine 1:
|
|
|
</span></span><span style="display:flex;"><span> main.main<span style="color:#f92672">()</span>
|
|
|
</span></span><span style="display:flex;"><span> race.go:15 +0x174
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span>Goroutine <span style="color:#ae81ff">5</span> <span style="color:#f92672">(</span>running<span style="color:#f92672">)</span> created at:
|
|
|
</span></span><span style="display:flex;"><span> time.goFunc<span style="color:#f92672">()</span>
|
|
|
</span></span><span style="display:flex;"><span> src/pkg/time/sleep.go:122 +0x56
|
|
|
</span></span><span style="display:flex;"><span> timerproc<span style="color:#f92672">()</span>
|
|
|
</span></span><span style="display:flex;"><span> src/pkg/runtime/ztime_linux_amd64.c:181 +0x189
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">==================</span>
|
|
|
</span></span></code></pre></div><h3 id="go-build--gcflags">
|
|
|
go build -gcflags
|
|
|
<a class="anchor" href="#go-build--gcflags">#</a>
|
|
|
</h3>
|
|
|
<p><code>-gcflags</code>选项用来设置编译器编译时参数,支持的参数有:</p>
|
|
|
<ul>
|
|
|
<li>-N选项指示禁止优化</li>
|
|
|
<li>-l选项指示禁止内联</li>
|
|
|
<li>-S选项指示打印出汇编代码</li>
|
|
|
<li>-m选项指示打印出变量变量逃逸信息,<code>-m -m</code>可以打印出更丰富的变量逃逸信息</li>
|
|
|
</ul>
|
|
|
<p><code>-gcflags</code>支持只在编译特定包时候才传递编译参数,此时的<code>-gcflags</code>格式为<code>包名=参数列表</code>。</p>
|
|
|
<pre tabindex="0"><code>go build -gcflags="-N -l -S" main.go // 打印出main.go对应的汇编代码
|
|
|
go build -gcflags="log=-N -l" main.go // 只对log包进行禁止优化,禁止内联操作
|
|
|
</code></pre><h2 id="go-tool-compile">
|
|
|
go tool compile
|
|
|
<a class="anchor" href="#go-tool-compile">#</a>
|
|
|
</h2>
|
|
|
<p><code>go tool compile</code>命令用于汇编处理Go 程序文件。<code>go tool compile</code>支持常见选项有:</p>
|
|
|
<ul>
|
|
|
<li>-N选项指示禁止优化</li>
|
|
|
<li>-l选项指示禁止内联</li>
|
|
|
<li>-S选项指示打印出汇编代码</li>
|
|
|
<li>-m选项指示打印出变量内存逃逸信息</li>
|
|
|
</ul>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>go tool compile -N -l -S main.go <span style="color:#75715e"># 打印出main.go对应的汇编代码</span>
|
|
|
</span></span><span style="display:flex;"><span>GOOS<span style="color:#f92672">=</span>linux GOARCH<span style="color:#f92672">=</span>amd64 go tool compile -N -l -S main.go <span style="color:#75715e"># 打印出针对特定系统和CPU架构的汇编代码</span>
|
|
|
</span></span></code></pre></div><h2 id="go-tool-nm">
|
|
|
go tool nm
|
|
|
<a class="anchor" href="#go-tool-nm">#</a>
|
|
|
</h2>
|
|
|
<p><code>go tool nm</code>命令用来查看Go 二进制文件中符号表信息。</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>go tool nm ./main | grep <span style="color:#e6db74">"runtime.zerobase"</span>
|
|
|
</span></span></code></pre></div><h2 id="go-tool-objdump">
|
|
|
go tool objdump
|
|
|
<a class="anchor" href="#go-tool-objdump">#</a>
|
|
|
</h2>
|
|
|
<p><code>go tool objdump</code>命令用来根据目标文件或二进制文件反编译出汇编代码。该命令支持两个选项:</p>
|
|
|
<ul>
|
|
|
<li>-S选项指示打印汇编代码</li>
|
|
|
<li>-s选项指示搜索相关的汇编代码</li>
|
|
|
</ul>
|
|
|
<pre tabindex="0"><code>go tool compile -N -l main.go # 生成main.o
|
|
|
go tool objdump main.o # 打印所有汇编代码
|
|
|
go tool objdump -s "main.(main|add)" ./test # objdump支持搜索特定字符串
|
|
|
</code></pre><h2 id="go-tool-trace">
|
|
|
go tool trace
|
|
|
<a class="anchor" href="#go-tool-trace">#</a>
|
|
|
</h2>
|
|
|
<h2 id="godebug环境变量">
|
|
|
GODEBUG环境变量
|
|
|
<a class="anchor" href="#godebug%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f">#</a>
|
|
|
</h2>
|
|
|
<p><code>GODEBUG</code>是控制运行时调试的变量,其参数以逗号分隔,格式为:name=val。<code>GODEBUG</code>可以用来观察GMP调度和GC过程。</p>
|
|
|
<h3 id="gmp调度">
|
|
|
GMP调度
|
|
|
<a class="anchor" href="#gmp%e8%b0%83%e5%ba%a6">#</a>
|
|
|
</h3>
|
|
|
<p>与GMP调度相关的两个参数:</p>
|
|
|
<ul>
|
|
|
<li>
|
|
|
<p>schedtrace:设置 schedtrace=X 参数可以使运行时在每 X 毫秒输出一行调度器的摘要信息到标准 err 输出中。</p>
|
|
|
</li>
|
|
|
<li>
|
|
|
<p>scheddetail:设置 schedtrace=X 和 scheddetail=1 可以使运行时在每 X 毫秒输出一次详细的多行信息,信息内容主要包括调度程序、处理器、OS 线程 和 Goroutine 的状态。</p>
|
|
|
</li>
|
|
|
</ul>
|
|
|
<p>我们以下面代码为例:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"sync"</span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"time"</span>
|
|
|
</span></span><span style="display:flex;"><span>)
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">wg</span> <span style="color:#a6e22e">sync</span>.<span style="color:#a6e22e">WaitGroup</span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> < <span style="color:#ae81ff">2000</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span> {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Add</span>(<span style="color:#ae81ff">1</span>)
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>() {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> < <span style="color:#ae81ff">1e6</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span> {
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">a</span> <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
|
|
|
</span></span><span style="display:flex;"><span> }
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Done</span>()
|
|
|
</span></span><span style="display:flex;"><span> }()
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Sleep</span>(<span style="color:#ae81ff">100</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Millisecond</span>)
|
|
|
</span></span><span style="display:flex;"><span> }
|
|
|
</span></span><span style="display:flex;"><span>
|
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Wait</span>()
|
|
|
</span></span><span style="display:flex;"><span>}
|
|
|
</span></span></code></pre></div><p>执行以下代码获取GMP调度信息:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>GODEBUG<span style="color:#f92672">=</span>schedtrace<span style="color:#f92672">=</span><span style="color:#ae81ff">1000</span> go run ./test.go
|
|
|
</span></span></code></pre></div><p>笔者本人电脑输出以下内容:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>SCHED 0ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">6</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">4</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 0ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">1</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 0ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 0ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 1007ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">16</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">9</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 1000ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span><span style="display:flex;"><span>SCHED 2018ms: gomaxprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> idleprocs<span style="color:#f92672">=</span><span style="color:#ae81ff">8</span> threads<span style="color:#f92672">=</span><span style="color:#ae81ff">16</span> spinningthreads<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> idlethreads<span style="color:#f92672">=</span><span style="color:#ae81ff">9</span> runqueue<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#f92672">[</span><span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> 0<span style="color:#f92672">]</span>
|
|
|
</span></span></code></pre></div><p>上面输出内容解释说明:</p>
|
|
|
<ul>
|
|
|
<li>SCHED XXms: SCHED是调度日志输出标志符。XXms是自程序启动之后到输出当前行时间</li>
|
|
|
<li>gomaxprocs: P的数量,等于当前的 CPU 核心数,或者GOMAXPROCS环境变量的值</li>
|
|
|
<li>idleprocs: 空闲P的数量,与gomaxprocs的差值即运行中P的数量</li>
|
|
|
<li>threads: 线程数量,即M的数量</li>
|
|
|
<li>spinningthreads:自旋状态线程的数量。当M没有找到可供其调度执行的 Goroutine 时,该线程并不会销毁,而是出于自旋状态</li>
|
|
|
<li>idlethreads:空闲线程的数量</li>
|
|
|
<li>runqueue:全局队列中G的数量</li>
|
|
|
<li>[0 0 0 0 0 0 0 0]:表示P本地队列下G的数量,有几个P中括号里面就会有几个数字</li>
|
|
|
</ul>
|
|
|
<h3 id="gc">
|
|
|
GC
|
|
|
<a class="anchor" href="#gc">#</a>
|
|
|
</h3>
|
|
|
<p>与 GC 相关的参数是 gctrace,当设置为1时候,会输出GC相关信息到标准错误输出。使用方式示例如下:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>GODEBUG<span style="color:#f92672">=</span>gctrace<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> go run main.go
|
|
|
</span></span></code></pre></div><p>GC 时候输出的内容格式如下:</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span>gc # <span style="color:#f92672">@</span>#s #<span style="color:#f92672">%</span>: #<span style="color:#f92672">+</span>#<span style="color:#f92672">+</span># ms clock, #<span style="color:#f92672">+</span>#<span style="color:#f92672">/</span>#<span style="color:#f92672">/</span>#<span style="color:#f92672">+</span># ms cpu, #->#-># <span style="color:#66d9ef">MB</span>, # <span style="color:#66d9ef">MB</span> goal, # P
|
|
|
</span></span></code></pre></div><p>格式解释说明如下:</p>
|
|
|
<ul>
|
|
|
<li><strong>gc #</strong>:GC 编号,每次 GC 时递增</li>
|
|
|
<li><strong>@#s</strong>:程序自启动以来的时间(单位秒)</li>
|
|
|
<li><strong>#%</strong>:程序自启动以来花费在 GC 上的时间百分比</li>
|
|
|
<li><strong>#+…+#</strong>:GC 各阶段花费的时间,分别为单个P的墙上时间和累计CPU时间</li>
|
|
|
<li><strong>#->#-># MB</strong>:分别表示 GC 启动时, GC 结束时, GC 活动时的堆大小</li>
|
|
|
<li><strong>#MB goal</strong>:下一次触发 GC 的内存占用阈值</li>
|
|
|
<li><strong>#P</strong>:当前使用的处理器P的数量</li>
|
|
|
</ul>
|
|
|
<p>比如对于下面的输出内容,详细解释如下:</p>
|
|
|
<blockquote>
|
|
|
<p>gc 100 @0.904s 11%: 0.043+2.8+0.029 ms clock, 0.34+3.4/5.4/13.6+0.23 ms cpu, 10->11->6 MB, 12 MB goal, 8 P</p>
|
|
|
</blockquote>
|
|
|
<ul>
|
|
|
<li><strong>gc 100</strong>:第 100 次 GC</li>
|
|
|
<li><strong>@0.904s</strong>:当前时间是程序启动后的0.904s</li>
|
|
|
<li><strong>11%</strong>:程序启动后到现在共花费 11% 的时间在 GC 上</li>
|
|
|
<li><strong>0.043+2.8+0.029 ms clock</strong>
|
|
|
<ul>
|
|
|
<li>0.043:表示单个 P 在 mark 阶段的 STW 时间</li>
|
|
|
<li>2.8:表示所有 P 的 concurrent mark(并发标记)所使用的时间</li>
|
|
|
<li>0.029:表示单个 P 的 markTermination 阶段的 STW 时间</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li><strong>0.34+3.4/5.4/0+0.23 ms cpu</strong>
|
|
|
<ul>
|
|
|
<li>0.34:表示整个进程在 mark 阶段 STW 停顿的时间,一共0.34秒,即 0.043 * 8</li>
|
|
|
<li>3.4/5.4/13.6:3.4 表示 mutator assist 占用的时间,5.4 表示 dedicated + fractional 占用的时间,13.6 表示 idle 占用的时间。这三块累计时间为22.4,即2.8 * 8</li>
|
|
|
<li>0.23 ms:0.23 表示整个进程在 markTermination 阶段 STW 时间,即0.029 * 8</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li><strong>10->11->6 MB</strong>
|
|
|
<ul>
|
|
|
<li>10:表示开始 mark 阶段前的 heap_live 大小</li>
|
|
|
<li>11:表示开始 markTermination 阶段前的 heap_live 大小</li>
|
|
|
<li>6:表示被标记对象的大小</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
<li><strong>12 MB goal</strong>:表示下一次触发 GC 回收的阈值是 12 MB</li>
|
|
|
<li><strong>8 P</strong>:本次 GC 一共涉及8 个P</li>
|
|
|
</ul>
|
|
|
<h4 id="gogc参数">
|
|
|
GOGC参数
|
|
|
<a class="anchor" href="#gogc%e5%8f%82%e6%95%b0">#</a>
|
|
|
</h4>
|
|
|
<p>Go语言GC相关的另外一个参数是GOGC。GOGC 用于控制GC的处发频率, 其值默认为100, 这意味着直到自上次垃圾回收后heap size已经增长了100%时GC才触发运行,live heap size每增长一倍,GC触发运行一次。若设定GOGC=200, 则live heap size 自上次垃圾回收后,增长2倍时,GC触发运行, 总之,其值越大则GC触发运行频率越低, 反之则越高。如果GOGC=off 则关闭GC。</p>
|
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># 表示当前应用占用的内存是上次GC时占用内存的两倍时,触发GC</span>
|
|
|
</span></span><span style="display:flex;"><span>export GOGC<span style="color:#f92672">=</span><span style="color:#ae81ff">100</span>
|
|
|
</span></span></code></pre></div><h2 id="进一步阅读">
|
|
|
进一步阅读
|
|
|
<a class="anchor" href="#%e8%bf%9b%e4%b8%80%e6%ad%a5%e9%98%85%e8%af%bb">#</a>
|
|
|
</h2>
|
|
|
<!-- raw HTML omitted -->
|
|
|
<ul>
|
|
|
<li>
|
|
|
<a href="https://eddycjy.gitbook.io/golang/di-9-ke-gong-ju/go-tool-trace">Go 大杀器之跟踪剖析 trace</a></li>
|
|
|
<li>
|
|
|
<a href="https://pkg.go.dev/runtime#hdr-Environment_Variables">go runtime Environment Variables</a></li>
|
|
|
</ul>
|
|
|
<div class="footnotes" role="doc-endnotes">
|
|
|
<hr>
|
|
|
<ol>
|
|
|
<li id="fn:1">
|
|
|
<p>
|
|
|
<a href="https://blog.golang.org/race-detector">Introducing the Go Race Detector</a> <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
|
|
</li>
|
|
|
</ol>
|
|
|
</div>
|
|
|
</article>
|
|
|
|
|
|
|
|
|
|
|
|
<footer class="book-footer">
|
|
|
|
|
|
<div class="flex flex-wrap justify-between">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</footer>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="book-comments">
|
|
|
|
|
|
<script src="https://giscus.app/client.js" data-repo="cyub/go-1.14.13"
|
|
|
data-repo-id="MDEwOlJlcG9zaXRvcnkzMzc2ODUyMzQ=" data-category="Announcements"
|
|
|
data-category-id="DIC_kwDOFCCq8s4CZ3BC"
|
|
|
data-mapping="pathname" data-strict="0" data-emit-metadata="0"
|
|
|
data-input-position="bottom" data-reactions-enabled="0"
|
|
|
data-lang="zh-CN" data-theme="preferred_color_scheme" crossorigin="anonymous" async>
|
|
|
</script>
|
|
|
<noscript>Please enable JavaScript to view the comments powered by giscus.</noscript>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<label for="menu-control" class="hidden book-menu-overlay"></label>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
</body>
|
|
|
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|