Actors Guild

Wednesday, February 24, 2010

On Hiatus

As you should have noticed, there has been no progress on AG in the last 6 months. The reason is simply that AG did not achieve what I had hoped, and I have gone on to pursue other things.

If you consider using AG in a project, you should be aware that it's unlikely that there will be any further development.

My current pet project is Jarfiller.com, a collection of very dense references and tutorials for Java developers.

Saturday, February 7, 2009

Actors Guild Framework 0.6

Version 0.6 of the Actors Guild Framework is now available. The focus of this release was to improve the API, simplify some features like the @Model annotation, and make it more difficult to write incorrect actors. Here is a list of the most important changes:
  • Property-based initialization (read more about it here)
  • Stateless classes will now be verified at runtime
  • For public non-@Message methods in actors the annotation ThreadSafe is now required
  • The Model annotation can only be used for whole actors, not for single messages anymore
As always, it would be great to get feedback of any kind!

The focus of the next release will be performance. I hope to improve the performance of the scheduler, and will introduce a much faster way of copying Serializable message arguments.

Saturday, January 24, 2009

AG 0.6's New Property-based Initialization

The most important change in the next Actors Guild version will be a complete rewrite of the initialization mechanism. So far initialization in AG imitated Java's constructors. There was a special message with an @Initializer annotation which was guaranteed to be always the first message to be executed in an actor. I never really liked this approach, but it was my first attempt.

My main grieve with the old @Initializer was that it did not work very well in a Dependency Injection environment. First of all, while AG 0.5 allowed writing properties (independent of the @Initializer), this would have been very error-prone. Typical Java property implementations, like the ones automatically generated by Eclipse, are not thread-safe. This is a problem, because values that you set during the initialization of an actor are not guaranteed to be visible in the threads that run the actor's messages. Secondly, it was not possible to set immutable final fields in the initializer, since it ran after the object's real constructor.

So for Actors Guild 0.6 I decided to take a completely different approach that's completely based on properties. One way to use it is to define standard Java properties in your actor class and then pass values for them to Agent.create(), which is AG's way of creating new actors. Let's say you have the following actor:
class Multiplicator {
private int m;

public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}

@Message
public AsyncResult multiply(int value) {
return result(getM() * value);
}
}

Then you can create a new instance with m=5 like this:
Agent agent = new DefaultAgent();
Mulitplicator mul = agent.create(Multiplicator.class, new Props("m", 5));

Even though the property accessors in Multiplicator are not thread-safe, it is guaranteed that any value set by Agent.create() is visible in the message implementations.

However, that would not be true if you had any other actors changing the m property by calling setM() from their threads. To be able to do this safely, the properties need to be synchronized. You could achieve this by adding a synchronized modifier to getM() and setM(). The easier way is to use AG's new property generation feature. Using the @Prop annotation you can let AG implement the accessors for you. Just implement abstract property accessors and annotate the getter with @Prop:
abstract class Multiplicator2 {
@Prop
public abstract int getM();
public abstract void setM(int m);

@Message
public AsyncResult multiply(int value) {
return result(getM() * value);
}
}

...
Mulitplicator2 mul = agent.create(Multiplicator2.class, new Props("m", 5));

@Prop generated methods are thread-safe by default. Thus you can also call them while the actor is already running (they will block while a message is being processed though).

To create a read-only property, just omit the setter. The generated code will create a final field to store the value. Read-only properties can only be set using Agent.create:
abstract class Multiplicator3 {
@Prop
public abstract int getM();

@Message
public AsyncResult multiply(int value) {
return result(getM() * value);
}
}

...
Mulitplicator3 mul = agent.create(Multiplicator3.class, new Props("m", 5));

So far it has been assumed that you always provide values for the properties in Agent.create(). In case you shouldn't, the property will be initialized to its default value (0 for numbers, false for boolean, null for references). If this is not a useful default value, you can declare a better one with a static final
field and the new @DefaultValue annotation. The following example defines a default value of 10 for the Multiplicator actor:
abstract class Multiplicator4 {
@DefaultValue("m") static final int DEFAULT_M = 10;

@Prop abstract int getM();

@Message
public AsyncResult multiply(int value) {
return result(getM() * value);
}
}

...
Mulitplicator4 mul = agent.create(Multiplicator4.class, new Props("m", 5));

Sometimes a default value is not enough, and you want to forbid certain values. Then you can use the @Initializer annotation to create an initializer method. Let's forbid negative values for m:
abstract class Multiplicator5 {
@DefaultValue("m") static final int DEFAULT_M = 10;

@Prop abstract int getM();

@Initializer
void init() {
if (m < 0)
throw new RuntimeException("Property m can not be negative!");
}

@Message
public AsyncResult multiply(int value) {
return result(getM() * value);
}
}

...
Mulitplicator5 mul = agent.create(Multiplicator5.class, new Props("m", 5));

The initializer can be used for other initialization work as well. Everything that is written in the initializer is always guaranteed to be visible in messages of the actor.


The @Prop, @DefaultValue and @Initializer annotations proved to be so useful that I also wanted to use them in regular beans. So I added a fourth annotation, @Bean, to declare a class as bean with auto-generated properties. @Bean has a mandatory parameter threadSafe which specifies whether the generated accessor methods for read-write properties will be synchronized or not (it does not have any effect on read-only properties which are always thread-safe). Here are two simple bean classes to represent points:
@Bean(threadSafe=true)
abstract class ImmutablePoint3D {
@Prop abstract double getX();
@Prop abstract double getY();
@Prop abstract double getZ();
}

@Bean(threadSafe=false)
abstract class MutablePoint3D {
@Prop abstract double getX();
abstract void setX(double x);

@Prop abstract double getY();
abstract void setY(double y);

@Prop abstract double getZ();
abstract void setZ(double z);
}

Like actors, @Bean annotated classes must be created using Agent.create:
DefaultAgent agent = new DefaultAgent();
ImmutablePoint3D p = agent.create(ImmutablePoint3D.class, new Props("x", 5.5).add("y", 10).add("z", -54.3));
MutablePoint3D p = agent.create(MutablePoint3D.class, new Props("x", 5.5).add("y", 10).add("z", -54.3));

Property-based initialization with @Prop, @DefaultValue, @Initializer and @Bean is already in SVN and will be the main feature of the Actors Guild Framework version 0.6. I hope to release it in the next week or two.

Saturday, January 3, 2009

Salmon Run / Actor Frameworks Compared

Sujit Pal has posted a very interesting comparison of Actor Frameworks. I am quite happy with the complexity of the AG Actors compared to those of the other frameworks (note that the Kilim actors have a super-class that does most of the work), and it will be even better in the next version with the initializer replacement (more on that later). The startup code in the ActorManager class became way to complicated, unfortunately, when I limited the size of the AsyncResult array in order to reduce memory consumption for a large number of tasks. You can see the original version here: http://pastebin.com/f4271c099. Maybe I am able to find a better way to support sending a very large number of tasks without processing them.
The performance of AG is not great, but quite ok considering that the messages are all one-way (AsyncResult<Void>) and the scheduler is not optimized yet. AG would be able to play out its strengths when the Actors would communicate in both directions. Then AG would be able to provide a return value without any additional overhead, while the other frameworks would need twice the amount of messages to achieve the same.

Saturday, December 27, 2008

Behind the Scenes: Actor Proxies

It is not possible to implement Actors Guild's functionality without generating or manipulating Java bytecode at runtime. AG intercepts invocations to @Message methods, queues the invocations and later invokes the original implementation. As AG does not need any preprocessor, it needs to create several dynamic helper classes for each actor at runtime.

Let's take the following Actor as an example to show the dynamic classes that AG will generate:
public class StringJoiner {
@Message
public AsyncResult<String> join(String separator, String[] parts) {
if (parts.length == 0)
return result("");

StringBuilder sb = new StringBuilder();
sb.append(part[0]);
for (int i = 1; i < parts.length; i++)
sb.append(separator).append(parts[i]);

return result(sb.toString());
}


Helper classes will be generated the first time the actor is created using Agent.create():
Agent ag = new DefaultAgent();
StringJoiner sj = ag.create(StringJoiner.class);


The most important helper class is the actor proxy. It is a sub-class of the original actor implementation that intercepts the messages. Actors Guild creates the byte code of its dynamic classes directly. As this would not be very readable, this is what the actor proxy class would look like in Java:
public final class StringJoiner__ACTORPROXY extends StringJoiner implements ActorProxy { // (1)
private final ActorState actorState__ACTORPROXY; // (2)
private final static MessageCaller messageCaller_0__ACTORPROXY; // (3)

static {
messageCaller_0__ACTORPROXY = new StringJoiner_join_0__MESSAGECALLER(); // (3)
}

public StringJoiner__ACTORPROXY(Controller controller) {
actorState__ACTORPROXY = new ActorState(controller, this, false); // (2)
}

public ActorState getState__ACTORPROXYMETHOD() { // (1)
return actorState__ACTORPROXY;
}

public AsyncResult join(String separator, String[] parts) { // (4)
Object[] args = new Object[2];
args[0] = separator;
args[1] = SerializableFreezer.freeze(parts);
actorState__ACTORPROXY.queueMessage(messageCaller_0__ACTORPROXY,
ConcurrencyModel.SingleThreaded, ThreadUsage.CpuBound, args);
}

public AsyncResult join__ACTORPROXYMETHOD_original(String separator, String[] parts) { // (5)
super.join(separator, parts);
}
}

(1)The proxy class has the name of the original actor with the postfix "__ACTORPROXY". The dynamic classes use this and other postfixes to prevent name conflicts with the user's own classes, because the generated classes always live in the same package as the user's classes. In order to override the message implementations (in this example, only join()), the proxy extends the Actor class. It also implements the ActorProxy interface which has only a single method getState_ACTORPROXYMETHOD(). The method allows retrieving the actor's ActorState object.

(2)The ActorState object contains the current state of the Actor. It contains things such as the actor's message queue, locking mechanisms and initialization state.

(3)For every message that the actor implements, there is one dynamically generated implementation of the MessageCaller interface. MessageCaller allows invoking the message implementations without using Java's reflection mechanisms. The implementation of the class StringJoiner_join_0__MESSAGECALLER will be shown below.

(4)The original implementation of the message will be overwritten by a message that puts the arguments into an object array and then calls the ActorState to queue the message. Arguments that are not immutable, such as the String array, will be frozen and copied using the helper class SerializableFreezer.

(5)This helper method is used by the MessageCaller to invoke the original message implementation, as an overridden method can only be called from sub-classes in Java.


Actors Guild generates an implementation of the MessageCaller interface for every message implementation in the actor. MessageCaller allows invocations of the method without the use of reflection. It is also responsible for unwrapping values in SerializableFreezers. The implementation for StringJoiner's join() method would look like this:
public final class StringJoiner_join_0__MESSAGECALLER implements MessageCaller {

public AsyncResult invoke(Actor actor, Object[] args) {
StringJoiner__ACTORPROXY a = (StringJoiner__ACTORPROXY) actor;
return a.invoke((String) args[0], (String[])((SerializableFreezer)args[1]).get());
}

public String getMessageName() {
return "join";
}
}

Finally, a third class is created for every Actor. It is a simple factory for the actor proxy and implements the ActorProxyFactory interface. ActorProxyFactory's only purpose is to avoid the use of reflection at runtime:
public final class StringJoiner__ACTORPROXYFACTOR implements ActorProxyFactory {

public ActorProxy createNewActor(Controller controller) {
return new StringJoiner__ACTORPROXY(controller);
}
}



Now that all the classes have been created for StringJoiner, the agent can start using them. First it obtains an ActorProxyFactory to create a new instance of the proxy class and return it:

Agent ag = new DefaultAgent();
StringJoiner sj = ag.create(StringJoiner.class);
System.out.println(sj.getClass());
// output: class StringJoiner__ACTORPROXY

When the join() method of the actor is invoked, the overriding implementation StringJoiner__ACTORPROXY.join() will intercept this call and put it in the ActorState's queue.

StringJoiner sj = ....;
AsyncResult<String> s = sj.join(",", new String[] { "a", "b", "c" });
System.out.println(s.get());
// output: a, b, c

The queued message will be either picked up by a worker thread that is looking for work, or it will be executed by the AsyncResult implementation when its await() or get() method is invoked - whatever comes first. In both cases, the generated MessageCaller invocation StringJoiner_join_0_MESSAGECALLER will be used to call the method StringJoiner__ACTORPROXY.join__ACTORPROXYMETHOD_original(), which can then invoke the original implementation StringJoiner.join(). Actors Guild's internal AsyncResult implementation will store the result and return it in get().

Sunday, December 21, 2008

Actors Guild: First Release (0.5)

I just released the first version of the Actors Guild Framework! Version 0.5 is ready for download. You can also visit the new site and read the tutorial.

Version 0.5 contains all the main features that I want to have in version 1.0. Still, please note that it is experimental software. There may be backward-incompatible changes in the API, in particular in the way actors are initialized. I would appreciate any feedback, especially concerning the API and how to make it easier to use.

This is my current to-do list for version 1.0:
  • support for dependency-injection in Actors
  • Spring support
  • run-time checks at the bytecode level to enforce the rules for Stateless messages
  • faster copying of mutable (Serializable) message arguments
I hope that you give give Actors Guild a try, and please leave some feedback either here on the blog, or write to tim@actorsguildframework.org. Thanks!

Saturday, November 29, 2008

Actors Guild Framework

This is the start of my Actors Guild blog. Actors Guild is a framework for concurrent programming in Java. A short introduction can be found on the Google Code project page, which also contains the source code (SVN) and JavaDocs.
I am currently working on a longer tutorial, the real homepage as well as some example code. Once this is done, I plan to release the first version (called 0.5, probably). If everything goes well, it's out on January 1.