asynkron / protoactor-go

Proto Actor - Ultra fast distributed actors for Go, C# and Java/Kotlin

Home Page:http://proto.actor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bad performance test ping/pong messages

kharitonov1995 opened this issue · comments

commented

I was using an old version of proto actor, now I saw the new version in Git and decided to upgrade. When I measured the number of message transfers, I saw that the processing is much faster in the old version.

The old version: (github.com/AsynkronIT/protoactor-go v0.0.0-20210125121722-bab29b9c335d)

goarch: amd64
pkg: go.num
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkProto
BenchmarkProto-8 785658 1504 ns/op
PASS

New version: (commit:66c886e5; dev branch)

goos: linux
goarch: amd64
pkg: limitconcurrency
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkProto
BenchmarkProto-8 198744 5538 ns/op
PASS

Code benchmark:

func testWork(ctx actor.Context) {
	if _, ok := ctx.Message().(string); ok {
		ctx.Respond("pong")
	}
}

func BenchmarkProto(b *testing.B) {
	system := actor.NewActorSystem()
	pid = system.Root.Spawn(actor.PropsFromFunc(testWork))
	for i := 0; i < b.N; i++ {
		_, err := system.Root.RequestFuture(pid, "ping", time.Second).Result()
		if err != nil {
			panic(err)
		}
	}
}

I'll take a peek at this.
In this specific test, the code will mostly wait for the mailbox to start running. there shouldn't be any changes to this pipeline for the different versions.
Did you run the tests multiple times? just to eliminate any other work done by the computer

commented

Thanks for the quick response! The PC is not doing any other work during the test. I tried to run it on another PC (several times), the result was the same.

commented

Wrote a little test. Here you can also see that the number of ping-pong messages was significantly higher in the old version.

type actor1 struct {
	t        time.Time
	deadline time.Time
	pid2     *actor.PID
	cnt      int
}

func (a *actor1) Receive(ctx actor.Context) {
	switch m := ctx.Message().(type) {
	case *actor.Started:
		a.deadline = a.t.Add(time.Second)
		ctx.Request(a.pid2, "ping")
	case string:
		if time.Now().After(a.deadline) {
			fmt.Println("total: ", a.cnt)
			return
		}
		if m == "pong" {
			a.cnt++
			ctx.Request(a.pid2, "ping")
		}
	}
}

func main() {
	system := actor.NewActorSystem()
	pid2 := system.Root.Spawn(actor.PropsFromFunc(func(ctx actor.Context) {
		if msg, ok := ctx.Message().(string); ok && msg == "ping" {
			ctx.Respond("pong")
		}
	}))
	a := &actor1{
		t:    time.Now(),
		pid2: pid2,
	}
	system.Root.Spawn(actor.PropsFromProducer(func() actor.Actor {
		return a
	}))
	<-make(chan bool)
}

Results:

  • OLD: total: 538204
  • NEW: total: 80031

Marking this up for grabs.
Nothing in the messaging pipeline has changed so I'm not really sure what could cause this.