{"id":299936,"date":"2020-03-10T15:00:50","date_gmt":"2020-03-10T15:00:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=299936"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=299936","title":{"rendered":"\u0411\u0443\u0444\u0435\u0440\u0430 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u044b"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/490618\/\">\n<p>\u0417\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438 \u0441\u043b\u0430\u0439\u0441\u043e\u0432 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435, \u043f\u043e\u0434\u043e\u0431\u043d\u043e std::array \u0432 C++ \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c \u0432 \u0421\u0438. \u041f\u0440\u043e \u0441\u0442\u0435\u043a \u0445\u043e\u0440\u043e\u0448\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b <a href=\"https:\/\/medium.com\/@blanchon.vincent\" rel=\"nofollow\">Vincent Blanchon<\/a> \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 <a href=\"https:\/\/medium.com\/a-journey-with-go\/go-how-does-the-goroutine-stack-size-evolve-447fc02085e5\" rel=\"nofollow\">Go: How Does the Goroutine Stack Size Evolve?<\/a>. \u0412\u0438\u043d\u0441\u0435\u043d\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u043a\u0430 \u0432 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430\u0445. \u0420\u0435\u0437\u044e\u043c\u0438\u0440\u0443\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430 2 KB;<\/li>\n<li>\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u043d\u0430 64 \u0431\u0438\u0442\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 1 GB;<\/li>\n<li>\u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0432\u043e\u0435;<\/li>\n<li>\u0441\u0442\u0435\u043a \u043a\u0430\u043a \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u0430\u043a \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412\u044b\u044f\u0441\u043d\u044e \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a \u0438 \u043a\u0430\u043a\u043e\u0439 \u043e\u0432\u0435\u0440\u0445\u0435\u0434 \u043c\u043e\u0436\u0435\u0442 \u0441 \u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u0438\u043d\u0435\u0441\u0442\u0438.<a name=\"habracut\"><\/a>\u0411\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c go 1.13.8 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u0441 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438 \u043e\u043f\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 <code>-gcflags=-m<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432 <code>runtime\/stack.go<\/code> \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 <code>stackDebug<\/code> \u0432 \u043d\u0443\u0436\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">const (     \/\/ stackDebug == 0: no logging     \/\/            == 1: logging of per-stack operations     \/\/            == 2: logging of per-frame operations     \/\/            == 3: logging of per-word updates     \/\/            == 4: logging of per-word reads     stackDebug       = 0     \/\/... )<\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"ochen-prostaya-programma\">\u041e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430<\/h4>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0443 \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u0447\u0442\u043e \u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0435\u043a \u043f\u043e\u0434 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  func main() { }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0438\u0434\u0438\u043c \u043a\u0430\u043a \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u043b \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u043c\u0438 2, 8, 32 KB:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ GOMAXPROCS=1 .\/app  stackalloc 32768   allocated 0xc000002000 stackalloc 2048 stackcacherefill order=0   allocated 0xc000036000 stackalloc 32768   allocated 0xc00003a000 stackalloc 8192 stackcacherefill order=2   allocated 0xc000046000 stackalloc 2048   allocated 0xc000036800 stackalloc 2048   allocated 0xc000037000 stackalloc 2048   allocated 0xc000037800 stackalloc 32768   allocated 0xc00004e000 stackalloc 8192   allocated 0xc000048000<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u041c\u043e\u0436\u0435\u043c \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c. <\/p>\n<p>  <\/p>\n<h4 id=\"ne-ochen-prostaya-programma\">\u043d\u0435 \u041e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430<\/h4>\n<p>  <\/p>\n<p>\u041a\u0443\u0434\u0430 \u0436\u0435 \u0431\u0435\u0437 <strong>Hello world<\/strong>!<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import &quot;fmt&quot;  func helloWorld()  {     fmt.Println(&quot;Hello world!&quot;) }  func main() {     helloWorld() }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">runtime: newstack sp=0xc000036348 stack=[0xc000036000, 0xc000036800]     morebuf={pc:0x41463b sp:0xc000036358 lr:0x0}     sched={pc:0x4225b1 sp:0xc000036350 lr:0x0 ctxt:0x0} stackalloc 4096 stackcacherefill order=1   allocated 0xc000060000 copystack gp=0xc000000180 [0xc000036000 0xc000036350 0xc000036800] -&gt; [0xc000060000 0xc000060b50 0xc000061000]\/4096 stackfree 0xc000036000 2048 stack grow done stackalloc 2048   allocated 0xc000036000 Hello world!<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0430\u0437\u043c\u0435\u0440\u0430 \u0432 2 KB \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u0438 \u043f\u043e\u0448\u043b\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 4 KB \u0431\u043b\u043e\u043a\u0430. \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0446\u0438\u0444\u0440\u0430\u043c\u0438 \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0445 \u0441\u043a\u043e\u0431\u043a\u0430\u0445. \u042d\u0442\u043e \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u043e \u043a\u0440\u0430\u044f\u043c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ Stack describes a Go execution stack. \/\/ The bounds of the stack are exactly [lo, hi), \/\/ with no implicit data structures on either side. type stack struct {     lo uintptr     hi uintptr }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u044d\u0442\u043e \u0430\u0434\u0440\u0435\u0441 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0435\u043a, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/... used := old.hi - gp.sched.sp \/\/... print(&quot;copystack gp=&quot;, gp, &quot; [&quot;, hex(old.lo), &quot; &quot;, hex(old.hi-used), &quot; &quot;, hex(old.hi), &quot;]&quot;, &quot; -&gt; [&quot;, hex(new.lo), &quot; &quot;, hex(new.hi-used), &quot; &quot;, hex(new.hi), &quot;]\/&quot;, newsize, &quot;\\n&quot;)<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443:<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>\u0417\u0430\u043f\u0438\u0441\u044c<\/th>\n<th>\u0420\u0430\u0437\u043c\u0435\u0440<\/th>\n<th>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>[0xc000036000 0xc000036350 0xc000036800]<\/td>\n<td>2048<\/td>\n<td>848<\/td>\n<\/tr>\n<tr>\n<td>[0xc000060000 0xc000060b50 0xc000061000]<\/td>\n<td>4096<\/td>\n<td>2896<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0433\u043e\u0440\u0443\u0442\u0438\u043d \u0447\u0442\u043e-\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f :<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import (     &quot;fmt&quot;     &quot;time&quot; )  func helloWorld()  {     fmt.Println(&quot;Hello world!&quot;) }  func main() {     for i := 0 ; i&lt; 12 ; i++ {         go helloWorld()     }      time.Sleep(5*time.Second) }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">$ .\/app 2&gt;&amp;1 | grep &quot;alloc 4&quot; stackalloc 4096 stackalloc 4096 stackalloc 4096 stackalloc 4096 stackalloc 4096<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443. \u041f\u043e\u0445\u043e\u0436\u0435 \u044d\u0442\u043e \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0443\u043b.<\/p>\n<p>  <\/p>\n<h4 id=\"massivy\">\u041c\u0430\u0441\u0441\u0438\u0432\u044b<\/h4>\n<p>  <\/p>\n<p>\u0412 <a href=\"https:\/\/github.com\/golang\/go\/blob\/master\/src\/runtime\/stack_test.go\" rel=\"nofollow\">stack_test.go<\/a> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u0430\u043b \u0441 \u043d\u0438\u0445. \u0412\u0437\u044f\u043b \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043e\u0434 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u043b <em>bigsize<\/em>, \u043f\u043e\u043a\u0430 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 <code>go build -gcflags=-m<\/code> \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c <code>main.go:8:6: moved to heap: x<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  const bigsize = 1024*1024*10 const depth = 50  \/\/go:noinline func step(i int) byte {     var x [bigsize]byte     if i != depth {         return x[i] * step(i+1)     } else {         return x[i]     } }  func main() {     step(0) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c 10 MB, \u0430 \u043f\u0440\u0438 depth &gt; 50 \u0437\u0430\u0432\u0435\u0442\u043d\u044b\u0439 <code>stack overflow<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043d\u0430\u043b\u043e\u0436\u0438\u043b \u0432\u044b\u0432\u043e\u0434 <code>-gcflags=&quot;-m&quot;<\/code><\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import (     &quot;fmt&quot;     &quot;os&quot; )  const bigsize = 1024 * 1024 * 10  func readSelf(buff []byte) int { \/\/ readSelf buff does not escape     f, err := os.Open(&quot;main.go&quot;) \/\/ inlining call to os.Open     if err != nil {         panic(err)     }      count, _ := f.Read(buff)     if err := f.Close(); err != nil { \/\/ inlining call to os.(*File).Close         panic(err)     }      return count }  func printSelf(buff []byte, count int) { \/\/ printSelf buff does not escape     tmp := string(buff[:count]) \/\/ string(buff[:count]) escapes to heap     \/\/ inlining call to fmt.Println     \/\/ tmp escapes to heap     \/\/ printSelf []interface {} literal does not escape     \/\/ io.Writer(os.Stdout) escapes to heap     fmt.Println(tmp) }  func foo() {     var data [bigsize]byte     cnt := readSelf(data[:])     printSelf(data[:], cnt) }  func main() {     foo() \/\/ can inline main }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043e\u0442\u043c\u0435\u0442\u0438\u043b \u0412\u0438\u043d\u0441\u0435\u043d\u0442, \u0441\u0442\u0435\u043a \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430, \u043d\u043e \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">stackalloc 2048 stackcacherefill order=0   allocated 0xc000042000 runtime: newstack sp=0xc00008ef40 stack=[0xc00008e000, 0xc00008f000]     morebuf={pc:0x48e4e0 sp:0xc00008ef50 lr:0x0}     sched={pc:0x48e4b8 sp:0xc00008ef48 lr:0x0 ctxt:0x0} stackalloc 8192 stackcacherefill order=2   allocated 0xc000078000 copystack gp=0xc000000180 [0xc00008e000 0xc00008ef48 0xc00008f000] -&gt; [0xc000078000 0xc000079f48 0xc00007a000]\/8192 stackfree 0xc00008e000 4096 stack grow done ... runtime: newstack sp=0xc0010aff40 stack=[0xc0008b0000, 0xc0010b0000]     morebuf={pc:0x48e4e0 sp:0xc0010aff50 lr:0x0}     sched={pc:0x48e4b8 sp:0xc0010aff48 lr:0x0 ctxt:0x0} stackalloc 16777216   allocated 0xc0010b0000 copystack gp=0xc000000180 [0xc0008b0000 0xc0010aff48 0xc0010b0000] -&gt; [0xc0010b0000 0xc0020aff48 0xc0020b0000]\/16777216 stackfree 0xc0008b0000 8388608 stack grow done<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043d\u0443\u0436\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432 \u0446\u0438\u043a\u043b\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0435\u043a.<\/p>\n<p>  <\/p>\n<h4 id=\"slaysy\">\u0421\u043b\u0430\u0439\u0441\u044b<\/h4>\n<p>  <\/p>\n<p>\u0421\u043b\u0430\u0439\u0441\u044b \u0434\u043e 64 KB \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u044b \u043d\u0430 \u0441\u0442\u0435\u043a\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">package main  import (     &quot;fmt&quot;     &quot;os&quot; )  const bigsize = 1024*64 - 1  func readSelf(buff []byte) int { \/\/ readSelf buff does not escape     f, err := os.Open(&quot;main.go&quot;) \/\/ inlining call to os.Open     if err != nil {         panic(err)     }      count, _ := f.Read(buff)     if err := f.Close(); err != nil { \/\/ inlining call to os.(*File).Close         panic(err)     }      return count }  func printSelf(buff []byte, count int) { \/\/ printSelf buff does not escape     tmp := string(buff[:count]) \/\/ string(buff[:count]) escapes to heap     \/\/ inlining call to fmt.Println     \/\/ tmp escapes to heap     \/\/ printSelf []interface {} literal does not escape     \/\/ io.Writer(os.Stdout) escapes to heap     fmt.Println(tmp) }  func foo() {     data := make([]byte, bigsize) \/\/ make([]byte, bigsize) does not escape     cnt := readSelf(data)     printSelf(data, cnt) }  func main() { \/\/ can inline main     foo() }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\">stackalloc 131072   allocated 0xc0000d0000 copystack gp=0xc000000180 [0xc0000c0000 0xc0000cff48 0xc0000d0000] -&gt; [0xc0000d0000 0xc0000eff48 0xc0000f0000]\/131072 stackfree 0xc0000c0000 65536<\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"proizvoditelnost-ili-eyo-otsutstvie\">\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438\u043b\u0438 \u0435\u0451 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435<\/h4>\n<p>  <\/p>\n<p>\u0412 Go \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043d\u0443\u043b\u0435\u0432\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c(<a href=\"https:\/\/tour.golang.org\/basics\/12\" rel=\"nofollow\">zero values<\/a>). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0436\u0438\u0434\u0430\u043c\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0432\u0435\u0440\u0445\u0435\u0434\u0430 \u043d\u0430 \u0437\u0430\u043d\u0443\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043d\u0435 \u0437\u043d\u0430\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0437\u044f\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u043d\u044f \u043a\u0435\u0439\u0441 \u0438 \u0441\u0440\u0430\u0432\u043d\u044e \u0441 sync.Pool.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u0435\u0439\u0441:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0447\u0438\u0442\u0430\u0435\u043c \u0432 \u0431\u0443\u0444\u0435\u0440(\u0438\u0437 \u0444\u0430\u0439\u043b\u0430);<\/li>\n<li>\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u0444\u0435\u0440;<\/li>\n<li>\u043f\u0438\u0448\u0435\u043c \u0431\u0443\u0444\u0435\u0440(\u0432 <code>\/dev\/null<\/code>).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u0430, \u044f \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u043c\u0435\u0440\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b. <\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u043a\u043e\u0434 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">func readSelf(buff []byte) int {     f, err := os.Open(&quot;bench_test.go&quot;)     if err != nil {         panic(err)     }      count, err := f.Read(buff)     if err != nil {         panic(err)     }      if err := f.Close(); err != nil {         panic(err)     }      return count }  func printSelf(buff []byte, count int) {     f, err := os.OpenFile(os.DevNull, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)     if err != nil {         panic(err)     }     if _, err := f.Write(buff[:count]); err != nil {         panic(err)     }      if err := f.Close(); err != nil {         panic(err)     } }  \/\/go:noinline func usePoolBlock4k() {     inputp := pool4blocks.Get().(*[]byte)     outputp := pool4blocks.Get().(*[]byte)      cnt := readSelf(*inputp)     copy(*outputp, *inputp)     printSelf(*outputp, cnt)      pool4blocks.Put(inputp)     pool4blocks.Put(outputp) }  \/\/go:noinline func useStackBlock4k() {     var input [block4k]byte     var output [block4k]byte      cnt := readSelf(input[:])     copy(output[:], input[:])     printSelf(output[:], cnt) }  func BenchmarkPoolBlock4k(b *testing.B) {     runtime.GC()     for i := 0; i &lt; 8; i++ {         data := pool4blocks.Get()         pool4blocks.Put(data)     }     for i := 0; i &lt; 8; i++ {         usePoolBlock4k()     }      b.ResetTimer()      for i := 0; i &lt; b.N; i++ {         usePoolBlock4k()     } }  func BenchmarkStackBlock4k(b *testing.B) {     runtime.GC()     for i := 0; i &lt; 8; i++ {         useStackBlock4k()     }     b.ResetTimer()      for i := 0; i &lt; b.N; i++ {         useStackBlock4k()     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<pre><code class=\"bash\">$ go test -bench=. -benchmem goos: linux goarch: amd64 pkg: gostack\/04_benchmarks BenchmarkPoolBlock4k-12           312918          3804 ns\/op         256 B\/op          8 allocs\/op BenchmarkStackBlock4k-12          313255          3833 ns\/op         256 B\/op          8 allocs\/op BenchmarkPoolBlock8k-12           300796          3980 ns\/op         256 B\/op          8 allocs\/op BenchmarkStackBlock8k-12          294266          4110 ns\/op         256 B\/op          8 allocs\/op BenchmarkPoolBlock16k-12          288734          4138 ns\/op         256 B\/op          8 allocs\/op BenchmarkStackBlock16k-12         269382          4408 ns\/op         256 B\/op          8 allocs\/op BenchmarkPoolBlock32k-12          272139          4407 ns\/op         256 B\/op          8 allocs\/op BenchmarkStackBlock32k-12         240339          4957 ns\/op         256 B\/op          8 allocs\/op PASS<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0434\u0432\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u043f\u043e 4 KB, \u0442\u043e \u0440\u0430\u0437\u043d\u0438\u043a\u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u0438. \u0421 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0431\u043b\u043e\u043a\u0430, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043f\u0443\u043b\u043e\u043c \u0438 \u0441\u0442\u0435\u043a\u043e\u043c. \u0412\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0432\u044b\u0432\u043e\u0434 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">(pprof) top 15 Showing nodes accounting for 7.99s, 79.58% of 10.04s total Dropped 104 nodes (cum &lt;= 0.05s) Showing top 15 nodes out of 85       flat  flat%   sum%        cum   cum%      3.11s 30.98% 30.98%      3.38s 33.67%  syscall.Syscall6      2.01s 20.02% 51.00%      2.31s 23.01%  syscall.Syscall      0.83s  8.27% 59.26%      0.83s  8.27%  runtime.epollctl      0.60s  5.98% 65.24%      0.60s  5.98%  runtime.memmove      0.21s  2.09% 67.33%      0.21s  2.09%  runtime.unlock      0.18s  1.79% 69.12%      0.18s  1.79%  runtime.nextFreeFast      0.14s  1.39% 70.52%      0.33s  3.29%  runtime.exitsyscall      0.14s  1.39% 71.91%      0.21s  2.09%  runtime.reentersyscall      0.13s  1.29% 73.21%      0.46s  4.58%  runtime.mallocgc      0.12s  1.20% 74.40%      1.25s 12.45%  gostack\/04_benchmarks.useStackBlock32k      0.12s  1.20% 75.60%      0.13s  1.29%  runtime.exitsyscallfast      0.11s  1.10% 76.69%      0.45s  4.48%  runtime.SetFinalizer      0.11s  1.10% 77.79%      0.11s  1.10%  runtime.casgstatus      0.10s     1% 78.78%      0.13s  1.29%  runtime.deferreturn      0.08s   0.8% 79.58%      1.24s 12.35%  gostack\/04_benchmarks.useStackBlock16k<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0432\u0438\u0434\u0438\u043c syscalls. \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430 <code>useStackBlock32k<\/code> \u0438 <code>getFromStack32k<\/code>. \u041e\u0432\u0435\u0440\u0445\u0435\u0434 \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b 120ms:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">(pprof) list useStackBlock32k Total: 10.04s ROUTINE ======================== useStackBlock32k in bench_test.go      120ms      1.25s (flat, cum) 12.45% of Total          .          .    158:   printSelf(output[:], cnt)          .          .    159:}          .          .    160:          .          .    161:\/\/go:noinline          .          .    162:func useStackBlock32k() {       90ms       90ms    163:   var input [block32k]byte       30ms       30ms    164:   var output [block32k]byte          .          .    165:          .      530ms    166:   cnt := readSelf(input[:])          .      160ms    167:   copy(output[:], input[:])          .      440ms    168:   printSelf(output[:], cnt)          .          .    169:}  ROUTINE ======================== usePoolBlock32k in bench_test.go       10ms      1.18s (flat, cum) 11.75% of Total          .          .    115:   pool16blocks.Put(outputp)          .          .    116:}          .          .    117:          .          .    118:\/\/go:noinline          .          .    119:func usePoolBlock32k() {          .       10ms    120:   inputp := pool32blocks.Get().(*[]byte)          .       10ms    121:   outputp := pool32blocks.Get().(*[]byte)          .          .    122:          .      520ms    123:   cnt := readSelf(*inputp)       10ms      200ms    124:   copy(*outputp, *inputp)          .      440ms    125:   printSelf(*outputp, cnt)          .          .    126:          .          .    127:   pool32blocks.Put(inputp)          .          .    128:   pool32blocks.Put(outputp)          .          .    129:}<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043c\u043e\u043c 10 MB;<\/li>\n<li>\u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u043b\u0430\u0439\u0441\u0430 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d 64 KB;<\/li>\n<li>\u0435\u0441\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043a\u0430;<\/li>\n<li>\u0435\u0441\u0442\u044c \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 <em>zero value<\/em>.<\/li>\n<\/ul>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/490618\/\"> https:\/\/habr.com\/ru\/post\/490618\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/490618\/\">\n<p>\u0417\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u0438 \u0441\u043b\u0430\u0439\u0441\u043e\u0432 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435, \u043f\u043e\u0434\u043e\u0431\u043d\u043e std::array \u0432 C++ \u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c \u0432 \u0421\u0438. \u041f\u0440\u043e \u0441\u0442\u0435\u043a \u0445\u043e\u0440\u043e\u0448\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b <a href=\"https:\/\/medium.com\/@blanchon.vincent\" rel=\"nofollow\">Vincent Blanchon<\/a> \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 <a href=\"https:\/\/medium.com\/a-journey-with-go\/go-how-does-the-goroutine-stack-size-evolve-447fc02085e5\" rel=\"nofollow\">Go: How Does the Goroutine Stack Size Evolve?<\/a>. \u0412\u0438\u043d\u0441\u0435\u043d\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0435\u043a\u0430 \u0432 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430\u0445. \u0420\u0435\u0437\u044e\u043c\u0438\u0440\u0443\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430 2 KB;<\/li>\n<li>\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u043d\u0430 64 \u0431\u0438\u0442\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 1 GB;<\/li>\n<li>\u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0435\u043a\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0432\u043e\u0435;<\/li>\n<li>\u0441\u0442\u0435\u043a \u043a\u0430\u043a \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u0430\u043a \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412\u044b\u044f\u0441\u043d\u044e \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a \u0438 \u043a\u0430\u043a\u043e\u0439 \u043e\u0432\u0435\u0440\u0445\u0435\u0434 \u043c\u043e\u0436\u0435\u0442 \u0441 \u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u0438\u043d\u0435\u0441\u0442\u0438.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-299936","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/299936","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=299936"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/299936\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=299936"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=299936"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=299936"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}