JoinActors: A Modular Library for Actors with Join Patterns

This paper presents an improved, modular version of the JoinActors library for Scala 3 that leverages metaprogramming to provide a developer-friendly API and an extensible architecture for integrating, comparing, and optimizing various join pattern matching algorithms, demonstrating significant performance gains over previous implementations while maintaining semantic correctness.

Ayman Hussein (Technical University of Denmark, Denmark), Philipp Haller (KTH Royal Institute of Technology, Sweden), Ioannis Karras (Technical University of Denmark, Denmark), Hernán Melgratti (University of Buenos Aires, Argentina / CONICET, Argentina), Alceste Scalas (Technical University of Denmark, Denmark), Emilio Tuosto (Gran Sasso Science Institute, Italy)

Published Mon, 09 Ma
📖 5 min read🧠 Deep dive

Imagine you are the manager of a busy, high-tech restaurant kitchen.

In a traditional kitchen (standard programming), when a waiter brings a new order to the counter, the chef looks at just that one ticket. If the ticket says "Burger," the chef starts making a burger. If it says "Salad," they start a salad. They handle one thing at a time.

But what if your restaurant has a special rule?

"We only serve the 'Royal Feast' if we have a Burger, a Salad, and a Wine order all sitting on the counter at the same time, AND the customer's name on all three tickets matches."

In a traditional kitchen, the chef would have to remember: "Okay, I have a burger. I need to wait for a salad. Oh, here's a salad, but I need to check the name. Now I have a wine... wait, does the name match? Did I lose the burger ticket?" The chef would have to keep a mental notepad of every single order, cross-referencing them constantly. It's messy, prone to errors, and slow.

JoinActors is like a magical, smart kitchen assistant that solves this problem.

The Problem: The "Wait for Everything" Dilemma

In the world of computer software, many programs work like this kitchen. Different parts of the system (actors) send messages to each other. Sometimes, a program needs to wait for a specific combination of messages before it can do its job.

Old ways of doing this required programmers to write complex, error-prone code to manually track: "Do I have Message A? Do I have Message B? Do they match? Is Message C here yet?" It's like trying to juggle while blindfolded.

The Solution: Join Patterns

Join Patterns are a way of saying, "Don't do anything until I have this specific group of things."

The JoinActors library (the focus of this paper) is a tool for the Scala programming language that lets developers write these rules easily. Instead of juggling, the developer just writes:

"If I see a Burger, a Salad, and a Wine with the same name, THEN cook the Royal Feast."

The library handles all the messy tracking in the background.

The Magic Trick: Metaprogramming

The paper highlights a cool trick called Metaprogramming.

Imagine you write a recipe on a piece of paper. Usually, a computer reads the paper and cooks. But with Metaprogramming, the computer reads your recipe before it even starts cooking, and it rewrites the recipe itself to be super efficient.

In JoinActors, when you write your "Wait for Burger, Salad, and Wine" rule, the library's "magic compiler" looks at your rule, understands exactly what you need, and automatically builds a highly optimized machine to watch for those specific items. You get the simplicity of writing a simple rule, but the speed of a custom-built machine.

The Secret Sauce: Modular Matching Algorithms

Here is where the paper gets really interesting.

In the past, if you used a library like this, you were stuck with one way of checking for messages. It was like having a kitchen with only one type of chef: a "Brute Force" chef who checks every single ticket against every other ticket, over and over again. It works, but it's slow if the kitchen gets crowded.

JoinActors is Modular. This means the "chef" isn't built-in; you can swap them out!

The authors created a toolkit with different types of "chefs" (algorithms) for different situations:

  1. The Brute Force Chef: Good for small kitchens, checks everything.
  2. The Tree-Master Chef: Builds a tree of possibilities. If a burger arrives, it instantly knows which salads and wines could match it. Very efficient.
  3. The Lazy Chef: Doesn't build the whole tree until it absolutely has to. Saves energy.
  4. The Parallel Chef: Uses multiple chefs working at the same time on different parts of the tree. Great for huge, busy kitchens.

The beauty of JoinActors is that the developer can choose the right chef for their specific job. If the kitchen is small, use the simple one. If it's a massive stadium event, use the Parallel Chef.

Why This Matters (The Results)

The authors tested these different "chefs" against the old, slow methods.

  • Speed: In some tests, the new optimized chefs were 50 to 200 times faster than the old ways.
  • Accuracy: They use a "Fair" system. In the old days, if two groups of messages could match, the computer might pick one randomly, leaving the other group waiting forever (starving). JoinActors ensures that the oldest messages get served first, so no one is left waiting indefinitely.
  • Flexibility: Because it's a library, you don't need to change the whole programming language (Scala) to use it. You just plug it in like a new app on your phone.

The Bottom Line

Think of JoinActors as a smart traffic control system for a busy city.

  • Old way: Every car (message) stops at a light, and a human guard manually checks if they can proceed based on other cars. Chaos.
  • JoinActors: The system automatically groups cars. It knows, "Ah, a red car, a blue car, and a green car are arriving together. They form a convoy. Let them all go through the intersection at once."

It makes complex, coordinated software easier to write, less likely to crash, and incredibly fast. The paper proves that by letting developers swap out the "traffic algorithms," they can make their software run significantly better, whether they are running a small app or a massive distributed system.