Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: don't emit writebarrier for stores to newly allocated objects #9755

Closed
dvyukov opened this Issue Feb 2, 2015 · 5 comments

Comments

Projects
None yet
4 participants
@dvyukov
Copy link
Member

commented Feb 2, 2015

Consider the following code:

x := &X{&obj, make([]int, n)}
...

Compiler transforms it to roughly the following code:

tmp0 := runtime.makeslice(int, n)
tmp1 := runtime.newobject(X)
runtime.writebarrierptr(&tmp1.f0, &obj)
runtime.writebarrierslice(&tmp1.f2, tmp0)

I suspect that barriers are unnecessary in this case because tmp1 is accessible only through the stack of the current goroutine. So &obj and tmp0 will be found and marked during stack scanning.

It seems that a simple approximation of the "is accessible only through the stack of the current goroutine" condition is "we have not yet encountered any calls since allocation of the object". That is:

tmp1 := runtime.newobject(X)
tmp1.f0 = ... // no write barrier
tmp1.f1 = ... // no write barrier
any function call
tmp1.f0 = ... // write barrier
tmp1.f2 = ... // write barrier

@dvyukov dvyukov added this to the Go1.5Maybe milestone Feb 2, 2015

@dvyukov

This comment has been minimized.

Copy link
Member Author

commented Feb 2, 2015

@dvyukov

This comment has been minimized.

Copy link
Member Author

commented Feb 2, 2015

I've calculated an optimistic approximation of the potential win by counting runtime.writebarrier calls right after runtime.newobject calls w/o any intervening calls in godoc binary.
Total number of writebarrier calls = 9732
writebarrier calls right after newobject = 2495
= ~25%

@RLH

This comment has been minimized.

Copy link
Contributor

commented Feb 2, 2015

I'm not sure the gain is as large as you imply with your 25% number. If the
write barrier is off then the compiler will eventually emit a normal path
of a load of gcphase, a compare, and a branch. Since the branch is
predictable any reasonable OOO machine will do a pretty good job hiding the
sequence. It will be great when we get to a point where these types of
performance optimizations are at the top of our list for increasing
performance.

On Mon, Feb 2, 2015 at 12:23 PM, Dmitry Vyukov notifications@github.com
wrote:

I've calculated an optimistic approximation of the potential win by
counting runtime.writebarrier calls right after runtime.newobject calls w/o
any intervening calls in godoc binary.
Total number of writebarrier calls = 9732
writebarrier calls right after newobject = 2495
= ~25%


Reply to this email directly or view it on GitHub
#9755 (comment).

@rsc rsc removed the repo-main label Apr 14, 2015

@rsc

This comment has been minimized.

Copy link
Contributor

commented May 19, 2015

The compiler now emits the needWriteBarrier check. I think that's enough for Go 1.5. We can revisit this if and when profiles show that we're spending too much time on things like this.

@rsc rsc modified the milestones: Unplanned, Go1.5Maybe May 19, 2015

@rsc rsc changed the title cmd/gc: don't emit writebarrier for stores to newly allocated objects cmd/compile: don't emit writebarrier for stores to newly allocated objects Jun 8, 2015

@randall77

This comment has been minimized.

Copy link
Contributor

commented Apr 2, 2019

This is fixed now; the following code has no write barriers:

package main

type X struct {
	p *int
	q []int
}

var obj int

func f(n int) {
	x := &X{&obj, make([]int, n)}
	g(x)
}

//go:noescape
func g(x *X)

@randall77 randall77 closed this Apr 2, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.