actor or standard class? - how to explore the differences

 Many times I was talking with developers about using an actor system as a way to gain productivity and scalability. What I found that most peoples had no experience and no time to try it out, moreover existing projects and teams are on the hesitating side as new stuff will require a learning time (and who want to learn when all is gooooing goooood and sloooow).

Let me share some concepts that were able to help me to understand and use actor system in C#, so we are talking about akka.net

First listing contains a class and an actor. Please read it carefully. 

listing 1:

What we can see at the first glance that actor class is inheriting after ReceiveActor, has a strange Receive<T>(). In standard approach when we create an instance of class c, then we are calling their methods and passing parameters to do the job. In actor system, we are not calling methods inside an actor - we are passing messages - so we need to receive them and then handle. 

This makes it a bit harder to debug in a standard way, as we were used to trace all the stack and calls from end to end, and here we have a invisible message bus, that disconnects sender and receiver.
So at this moment we can say that the actor need more operations to conduct an action. That's true for the first action.

Let's consider a scenario, when our actor receives a calls from an api-endpoint to create a book entry and same in standard approach.

To demonstrate that we will use a minimal api project, and let's try to go to the details as they will be revelated later.
As a task we  need to save incoming book details into a text file, just for simplicity we will skip database interactions.

Below listing is using minimal apis with a .Net project template named pb-akka-web (here details)
listing 2 all in one...


So let's focus on the code for a moment.
We have 2 post endpoints, that are receiving same data object with book details. One endpoint is passing data to actor and the other is processing it in a classic way.
Now please have a moment to think: 

  • what can go wrong with this code?
  • how it will behave when we will have concurrent requests?
  • do you understand the flow with an actor?

So, let's run a JMeter benchmark for 1 user and 10000 requests for both actions, one by one.


for a classic approach we got:

and with an actor:


As we can see with a single user hitting our API there is almost no difference, so let's change that to 5 concurrent users and see the resultus. Any thoughts?

Now with an actor, ach not. Need to restart my Win as hit internal tcp limit of ephemeral tcp ports... So we will do 5 users@5k requests, so total of 25k request per trial.

I forgot to downsize the requests amount, but after registry fix and restart we were able to run this 50k requests. As we can see, 5 users generated 2x throughput, so we hit a bottle-neck with our file writer.
Let's run same for a standard approach with same code.

The results:

What??? Slower, and errors? Are they server errors or JMeter tcp again?


Ach. that is a real 500 from the server, 

Ach, wait - why we did not have this issue when using an actor? An actor processes one message at a time, so the file is accessed only once a time and we don't need to worry about concurrency (that's a huge gain for us).

So at the moment all looks very similar, nothing extraordinary different. In next post, we will switch our data storage to database and see how that will work and what we can do with an actor to gain performance.




 












Comments

Popular posts from this blog

when a new guy joins a team...

FizzBuzz - my first interview task on whiteboard

are YOU a garbage collector?