{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/11911","labels_url":"https://api.github.com/repos/golang/go/issues/11911/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/11911/comments","events_url":"https://api.github.com/repos/golang/go/issues/11911/events","html_url":"https://github.com/golang/go/issues/11911","id":97760743,"number":11911,"title":"runtime: unbounded heap growth with concurrent GC","user":{"login":"dvyukov","id":1095328,"avatar_url":"https://avatars.githubusercontent.com/u/1095328?v=3","gravatar_id":"","url":"https://api.github.com/users/dvyukov","html_url":"https://github.com/dvyukov","followers_url":"https://api.github.com/users/dvyukov/followers","following_url":"https://api.github.com/users/dvyukov/following{/other_user}","gists_url":"https://api.github.com/users/dvyukov/gists{/gist_id}","starred_url":"https://api.github.com/users/dvyukov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dvyukov/subscriptions","organizations_url":"https://api.github.com/users/dvyukov/orgs","repos_url":"https://api.github.com/users/dvyukov/repos","events_url":"https://api.github.com/users/dvyukov/events{/privacy}","received_events_url":"https://api.github.com/users/dvyukov/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"aclements","id":2688315,"avatar_url":"https://avatars.githubusercontent.com/u/2688315?v=3","gravatar_id":"","url":"https://api.github.com/users/aclements","html_url":"https://github.com/aclements","followers_url":"https://api.github.com/users/aclements/followers","following_url":"https://api.github.com/users/aclements/following{/other_user}","gists_url":"https://api.github.com/users/aclements/gists{/gist_id}","starred_url":"https://api.github.com/users/aclements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aclements/subscriptions","organizations_url":"https://api.github.com/users/aclements/orgs","repos_url":"https://api.github.com/users/aclements/repos","events_url":"https://api.github.com/users/aclements/events{/privacy}","received_events_url":"https://api.github.com/users/aclements/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/1","html_url":"https://github.com/golang/go/milestones/Go1.5","labels_url":"https://api.github.com/repos/golang/go/milestones/1/labels","id":905105,"number":1,"title":"Go1.5","description":"","creator":{"login":"bradfitz","id":2621,"avatar_url":"https://avatars.githubusercontent.com/u/2621?v=3","gravatar_id":"","url":"https://api.github.com/users/bradfitz","html_url":"https://github.com/bradfitz","followers_url":"https://api.github.com/users/bradfitz/followers","following_url":"https://api.github.com/users/bradfitz/following{/other_user}","gists_url":"https://api.github.com/users/bradfitz/gists{/gist_id}","starred_url":"https://api.github.com/users/bradfitz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bradfitz/subscriptions","organizations_url":"https://api.github.com/users/bradfitz/orgs","repos_url":"https://api.github.com/users/bradfitz/repos","events_url":"https://api.github.com/users/bradfitz/events{/privacy}","received_events_url":"https://api.github.com/users/bradfitz/received_events","type":"User","site_admin":false},"open_issues":16,"closed_issues":1064,"state":"open","created_at":"2014-12-16T02:26:41Z","updated_at":"2015-07-30T21:41:11Z","due_on":"2015-07-31T04:00:00Z","closed_at":null},"comments":11,"created_at":"2015-07-28T17:43:00Z","updated_at":"2015-07-30T21:54:40Z","closed_at":null,"body":"The following program has live set of at most 100MB . With GODEBUG=gcstoptheworld=1 RSS stabilizes at ~204MB according to top, which makes sense. However with GODEBUG=gcstoptheworld=0 RSS steadily chaotically grows over time, I waited only for few minutes and RSS grew to 1106MB, one of the jumps was from 212MB to 678MB in one second. GOMAXPROCS value may have effect on this, I've get the worst numbers with GOMAXPROCS=2/4, however I did not make an exhaustive investigation, maybe GOMAXPROCS is red herring.\r\n\r\n```go\r\npackage main\r\n\r\nimport (\r\n\t\"math/rand\"\r\n\t\"sync\"\r\n\t\"sync/atomic\"\r\n\t\"unsafe\"\r\n)\r\n\r\nvar (\r\n\tgs, retained, seed int32\r\n\tmu                 sync.Mutex\r\n\tblocks             [][]*byte\r\n\tsink               = make([]byte, 4096)\r\n)\r\n\r\nconst (\r\n\tmaxGs       = 100\r\n\tmaxRetained = 100 << 20\r\n\tmaxBlock    = 64 << 10\r\n)\r\n\r\nfunc main() {\r\n\tgo worker()\r\n\tselect {}\r\n}\r\n\r\nfunc worker() {\r\n\trnd := rand.New(rand.NewSource(int64(atomic.AddInt32(&seed, 1))))\r\n\tss := unsafe.Sizeof(&gs)\r\n\tvar local [][]*byte\r\nloop:\r\n\tfor {\r\n\t\tswitch r := rnd.Intn(1000); {\r\n\t\tcase r == 0 || r == 1:\r\n\t\t\tif !tryAdd(&gs, 1, maxGs, 1) {\r\n\t\t\t\tcontinue loop\r\n\t\t\t}\r\n\t\t\tgo worker()\r\n\t\tcase r == 2:\r\n\t\t\tif !tryAdd(&gs, 1, maxGs, -1) {\r\n\t\t\t\tcontinue loop\r\n\t\t\t}\r\n\t\t\ts := 0\r\n\t\t\tfor _, b := range local {\r\n\t\t\t\ts += len(b)\r\n\t\t\t}\r\n\t\t\tlocal = nil\r\n\t\t\tif !tryAdd(&retained, 0, maxRetained, -int32(s)*int32(ss)) {\r\n\t\t\t\tpanic(\"bad\")\r\n\t\t\t}\r\n\t\t\treturn\r\n\t\tcase r < 300:\r\n\t\t\ts := maxBlock / int(ss)\r\n\t\t\tif !tryAdd(&retained, 0, maxRetained, int32(s)*int32(ss)) {\r\n\t\t\t\tcontinue loop\r\n\t\t\t}\r\n\t\t\tb := make([]*byte, s)\r\n\t\t\tp := &sink[len(sink)-1]\r\n\t\t\tfor i := range b {\r\n\t\t\t\tb[i] = p\r\n\t\t\t}\r\n\t\t\tmu.Lock()\r\n\t\t\tblocks = append(blocks, b)\r\n\t\t\tmu.Unlock()\r\n\t\tcase r < 500:\r\n\t\t\ts := 0\r\n\t\t\tmu.Lock()\r\n\t\t\tif len(blocks) > 0 {\r\n\t\t\t\tidx := rnd.Intn(len(blocks))\r\n\t\t\t\ts = len(blocks[idx])\r\n\t\t\t\tblocks[idx] = blocks[len(blocks)-1]\r\n\t\t\t\tblocks[len(blocks)-1] = nil\r\n\t\t\t\tblocks = blocks[:len(blocks)-1]\r\n\t\t\t}\r\n\t\t\tmu.Unlock()\r\n\t\t\tif !tryAdd(&retained, 0, maxRetained, -int32(s)*int32(ss)) {\r\n\t\t\t\tpanic(\"bad\")\r\n\t\t\t}\r\n\t\tcase r < 800:\r\n\t\t\ts := maxBlock / int(ss)\r\n\t\t\tif !tryAdd(&retained, 0, maxRetained, int32(s)*int32(ss)) {\r\n\t\t\t\tcontinue loop\r\n\t\t\t}\r\n\t\t\tb := make([]*byte, s)\r\n\t\t\tp := &sink[len(sink)-1]\r\n\t\t\tfor i := range b {\r\n\t\t\t\tb[i] = p\r\n\t\t\t}\r\n\t\t\tlocal = append(local, b)\r\n\t\tdefault:\r\n\t\t\ts := 0\r\n\t\t\tif len(local) > 0 {\r\n\t\t\t\tidx := rnd.Intn(len(local))\r\n\t\t\t\ts = len(local[idx])\r\n\t\t\t\tlocal[idx] = local[len(local)-1]\r\n\t\t\t\tlocal[len(local)-1] = nil\r\n\t\t\t\tlocal = local[:len(local)-1]\r\n\t\t\t}\r\n\t\t\tif !tryAdd(&retained, 0, maxRetained, -int32(s)*int32(ss)) {\r\n\t\t\t\tpanic(\"bad\")\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunc tryAdd(p *int32, min, max, v int32) bool {\r\n\tfor {\r\n\t\told := atomic.LoadInt32(p)\r\n\t\txchg := old + v\r\n\t\tif xchg < min || xchg > max {\r\n\t\t\treturn false\r\n\t\t}\r\n\t\tif atomic.CompareAndSwapInt32(p, old, xchg) {\r\n\t\t\treturn true\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\ngo version devel +d0729a6 Tue Jul 28 06:23:38 2015 +0000 linux/amd64"},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/126504297","html_url":"https://github.com/golang/go/issues/11911#issuecomment-126504297","issue_url":"https://api.github.com/repos/golang/go/issues/11911","id":126504297,"user":{"login":"aclements","id":2688315,"avatar_url":"https://avatars.githubusercontent.com/u/2688315?v=3","gravatar_id":"","url":"https://api.github.com/users/aclements","html_url":"https://github.com/aclements","followers_url":"https://api.github.com/users/aclements/followers","following_url":"https://api.github.com/users/aclements/following{/other_user}","gists_url":"https://api.github.com/users/aclements/gists{/gist_id}","starred_url":"https://api.github.com/users/aclements/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aclements/subscriptions","organizations_url":"https://api.github.com/users/aclements/orgs","repos_url":"https://api.github.com/users/aclements/repos","events_url":"https://api.github.com/users/aclements/events{/privacy}","received_events_url":"https://api.github.com/users/aclements/received_events","type":"User","site_admin":false},"created_at":"2015-07-30T21:54:40Z","updated_at":"2015-07-30T21:54:40Z","body":"I've reproduced the remaining assist failure twice now and both times in the failing cycle we also swept several thousand spans at the beginning of that cycle. We're not supposed to be sweeping *any* spans (and usually we don't). This suggests that some accounting is off and it's throwing off both the sweep ratio and the assist ratio. This sweeping is also bad for the mutator yielding trick because mutators that are allocating wind up yielding a lot during this sweep process."}}