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

feat: Promise/Future for multi-consumer async acquiring result #221

Closed
wants to merge 4 commits into from

Conversation

jizhuozhi
Copy link

The syncx.Promise provides a facility to store a value or an error that is later acquired asynchronously via a syncx.Future created by the syncx.Promise object. Note that the syncx.Promise object is meant to be used only once.

As same as std::promise and std::future in C++(https://en.cppreference.com/w/cpp/thread/promise)

@NX-Official
Copy link
Contributor

NX-Official commented Jul 11, 2024

Use sync.WaitGroup and atomic.CompareAndSwapInt32 maybe can make code cleaner and more efficient 🧐

type state struct {
	// ...
	wg   sync.WaitGroup
}

func newState() *state {
	s := &state{}
	s.wg.Add(1)
	return s
}

func (s *state) set(val interface{}, err error) {
	if atomic.CompareAndSwapInt32(&s.done, 0, 1) {
		s.val, s.err = val, err
		s.wg.Done()
	} else {
		panic("promise already satisfied")
	}
}

func (s *state) get() (interface{}, error) {
	s.wg.Wait()
	return s.val, s.err
}
func BenchmarkPromiseAndFuture(b *testing.B) {
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		p := NewPromise()
		f := p.Future()

		go func() {
			p.Set(1, errFoo)
		}()

		_, _ = f.Get()
	}
}

current version

goos: linux
goarch: amd64
pkg: github.com/bytedance/gopkg/lang/syncx
cpu: AMD Ryzen 7 4700G with Radeon Graphics         
BenchmarkPromiseAndFuture
BenchmarkPromiseAndFuture-16    	 1915816	       633.9 ns/op	     168 B/op	       4 allocs/op
PASS

new version

goos: linux
goarch: amd64
pkg: github.com/bytedance/gopkg/lang/syncx
cpu: AMD Ryzen 7 4700G with Radeon Graphics         
BenchmarkPromiseAndFuture
BenchmarkPromiseAndFuture-16    	 2030475	       590.7 ns/op	     104 B/op	       3 allocs/op
PASS

@jizhuozhi
Copy link
Author

Promise/Future has reimplemented using sema primitives, and its performance is now better than sync.WaitGroup.

goos: darwin
goarch: arm64
pkg: github.com/bytedance/gopkg/lang/syncx
Benchmark
Benchmark/Promise
Benchmark/Promise-12         	 2950075	       392.0 ns/op
Benchmark/WaitGroup
Benchmark/WaitGroup-12       	 2714890	       442.5 ns/op
Benchmark/Channel
Benchmark/Channel-12         	 2666980	       417.7 ns/op
PASS

@jizhuozhi jizhuozhi closed this Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants