{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/14921","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/14921/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/14921/comments","events_url":"https://api.github.com/repos/golang/go/issues/14921/events","html_url":"https://github.com/golang/go/issues/14921","id":142809072,"number":14921,"title":"runtime, cmd/compile: consider write barrier short-circuit when *dst == src","user":{"login":"josharian","id":67496,"avatar_url":"https://avatars.githubusercontent.com/u/67496?v=3","gravatar_id":"","url":"https://api.github.com/users/josharian","html_url":"https://github.com/josharian","followers_url":"https://api.github.com/users/josharian/followers","following_url":"https://api.github.com/users/josharian/following{/other_user}","gists_url":"https://api.github.com/users/josharian/gists{/gist_id}","starred_url":"https://api.github.com/users/josharian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josharian/subscriptions","organizations_url":"https://api.github.com/users/josharian/orgs","repos_url":"https://api.github.com/users/josharian/repos","events_url":"https://api.github.com/users/josharian/events{/privacy}","received_events_url":"https://api.github.com/users/josharian/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/golang/go/labels/Performance","name":"Performance","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/6","html_url":"https://github.com/golang/go/milestones/Unplanned","labels_url":"https://api.github.com/repos/golang/go/milestones/6/labels","id":1055141,"number":6,"title":"Unplanned","description":"No plan to fix in any specific release.\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":1240,"closed_issues":293,"state":"open","created_at":"2015-04-06T20:47:19Z","updated_at":"2016-03-24T16:57:55Z","due_on":"2099-12-31T05:00:00Z","closed_at":null},"comments":7,"created_at":"2016-03-22T23:20:12Z","updated_at":"2016-03-24T17:12:57Z","closed_at":null,"body":"I did a quick and dirty instrumentation of `writebarrierptr` and found that when executing `cmd/compile` to build std, about 25% of calls on average had `*dst == src`. In that case, there's no need to do the actual assignment or gray any objects (I think). I don't know how (a)typical that 25% number is.\r\n\r\nWe should investigate whether checking for this and short-circuiting is a net performance gain, in general. There are multiple places in the stack this could occur:\r\n\r\n(1) writebarrierptr (and friends)\r\n\r\nAdd\r\n\r\n```go\r\nif *dst == src {\r\n  return\r\n}\r\n```\r\n\r\nto the beginning of the method.\r\n\r\n(2) Wrapper routines\r\n\r\nAdd checks like:\r\n\r\n```go\r\nif dst[1] != src[1] {\r\n\twritebarrierptr(&dst[1], src[1])\r\n}\r\n```\r\n\r\nto the runtime routines that call `writebarrierptr`, like the wbfat.go routines, and `writebarrierstring` and friends. This is different than (1) insofar as it skips the `writebarrierptr` function call instead of having it return immediately.\r\n\r\n(3) Generated code\r\n\r\nWe currently generate wb-calling code like:\r\n\r\n```go\r\nif writeBarrier.enabled {\r\n  writebarrierptr(dst, src)\r\n} else {\r\n  *dst = src\r\n}\r\n```\r\n\r\nWe could instead generate code like:\r\n\r\n```go\r\nif *dst != src {\r\n  if writeBarrier.enabled {\r\n    writebarrierptr(dst, src)\r\n  } else {\r\n    *dst = src\r\n  }\r\n}\r\n```\r\n\r\ncc @aclements @randall77 \r\n\r\nI don't plan to work on this soon, as I need to undistract myself.\r\n"},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/200932259","html_url":"https://github.com/golang/go/issues/14921#issuecomment-200932259","issue_url":"https://api.github.com/repos/golang/go/issues/14921","id":200932259,"user":{"login":"josharian","id":67496,"avatar_url":"https://avatars.githubusercontent.com/u/67496?v=3","gravatar_id":"","url":"https://api.github.com/users/josharian","html_url":"https://github.com/josharian","followers_url":"https://api.github.com/users/josharian/followers","following_url":"https://api.github.com/users/josharian/following{/other_user}","gists_url":"https://api.github.com/users/josharian/gists{/gist_id}","starred_url":"https://api.github.com/users/josharian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josharian/subscriptions","organizations_url":"https://api.github.com/users/josharian/orgs","repos_url":"https://api.github.com/users/josharian/repos","events_url":"https://api.github.com/users/josharian/events{/privacy}","received_events_url":"https://api.github.com/users/josharian/received_events","type":"User","site_admin":false},"created_at":"2016-03-24T17:12:57Z","updated_at":"2016-03-24T17:12:57Z","body":"Thinking out loud, one interesting aspect of modifying the calling code (3 above) is that it might allow other optimization passes to remove the code entirely by proving that `*dst == src`. I guess that depends on whether `*dst` is actually a load or is an ssa.Value."}}