Skip to content

Commit

Permalink
benchmark; readme
Browse files Browse the repository at this point in the history
  • Loading branch information
nikandfor committed Jan 7, 2024
1 parent 164052e commit d28d1d5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 33 deletions.
48 changes: 15 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ This is all without timeouts, additional goroutines, allocations, and channels.
## Usage

```
// General pattern is
// QueueIn -> Enter -> defer Exit -> Commit/Cancel/return/panic
var sum int
bc := batch.Controller[int]{
bc := batch.Coordinator[int]{
// Required
Commit: func(ctx context.Context) (int, error) {
// commit sum
Expand All @@ -37,18 +40,22 @@ bc := batch.Controller[int]{
for j := 0; j < N; j++ {
go func(j int) {
ctx := context.WithValue(ctx, workerID{}, j) // can be obtained in Controller.Commit
ctx := context.WithValue(ctx, workerID{}, j) // can be obtained in Coordinator.Commit
bc.QueueIn() // let others know we are going to join
b, i := bc.Enter(true)
defer b.Exit()
data := 1 // prepare data
if i == 0 { // we are first in batch, reset it
sum = 0 // or you can do in in the end of commit function
idx := bc.Enter(true)
defer bc.Exit()
if idx == 0 { // we are first in the batch, reset it
sum = 0
}
sum++ // add work to the batch
sum += data // add data to the batch
res, err := b.Commit(ctx)
res, err := bc.Commit(ctx, false)
if err != nil { // works the same as we had independent commit in each goroutine
_ = err
}
Expand All @@ -59,31 +66,6 @@ for j := 0; j < N; j++ {
}
```

Lower level API allows queue up in advance, before actually entering batch.
This can be used instead of waiting for timeout for other workers to come.
Instead workers declare itself and now they may be a bit late.

```
b := bc.Batch()
defer b.Exit() // should be called with defer to outlive panics
b.QueueUp() // now we will be waited for.
// prepare data
x := 3
b.Enter(true) // enter syncronized section
// add data to a common batch
sum += x
_, _ = b.Commit(ctx)
// we are still in syncronized section until Exit is called
```

`Controller.Enter` is a shortcut for `Controller.Batch, Batch.QueueUp, Batch.Enter`.

Batch is error and panic proof which means the user code can return error or panic in any place,
but as soon as all workers left the batch its state is reset.
But not the external state, it's callers responsibility to keep it consistent.
45 changes: 45 additions & 0 deletions batch4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,48 @@ func TestCoordinatorAllCases(tb *testing.T) {

wg.Wait()
}

func BenchmarkCoordinator(tb *testing.B) {
tb.ReportAllocs()

ctx := context.Background()

var sum int

bc := batch.Coordinator[int]{
CommitFunc: func(ctx context.Context) (int, error) {
return sum, nil
},
}

tb.RunParallel(func(tb *testing.PB) {
for tb.Next() {
func() {
bc.QueueIn()

// runtime.Gosched()

idx := bc.Enter(true)
defer bc.Exit()

// tb.Logf("worker %2d iter %2d enters %2d", j, i, idx)

if idx == 0 {
sum = 0
}

sum += 1

res, err := bc.Commit(ctx, false)
if err != nil {
// tb.Errorf("commit: %v", err)
_ = err
}

// tb.Logf("worker %2d iter %2d res %2d %v", j, i, res, err)

_ = res
}()
}
})
}

0 comments on commit d28d1d5

Please sign in to comment.