Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

How do you Identify Actors?

Hi guys,

First of all I have good news: I got the go to use and modify the Message Maker source, so I will be able to post it soon - a soon as I come to a version which is really a good candidate for further development.

I want to make the zero coupled message creation useful for all kinds of message mediators (the actor that receives the message from one actor and sends it to the final receiver actor. Let's call it controller from now on.)

There are methods for message transmission which needs to identify the sender actor. For example if you have many instances of the same sender actor, but only one instance of controller.

As a first implementation I included the Message Enqueuer class in the message sent by the sender actor. In the controller I stored the Message Enqueuers of the the launched classes in a mapping array which shows sender to receiver(s) mapping.

When a message arrives I search through the array of Message Enqueuer classes of the senders to find the match. It works but not efficient. I have made tests (You can have a look at my test vi in the attachments: "QueueClass.zip" Just change the array input wiring from one array to the other to compare.) and found that in case of only 100 queue classes I have 170000 match/sec. The same measurement for a 100 sized array of U32s is about 6000000 match/sec. It gets worse for more queues.

So I really would like to have a unique integer numeric ID for an actor. As the only thing we can access after launching an actor is the queue to it, the queue reference converted to number would perfectly do it. I have made my first try by adding one method to the Message Priority Queue class which converts the Priority queue to U32 Refnum:

MessagePriorityQueueClass_NewMethod.png

Another method is added to Message Enqueuer class to pass the Refnum out to the "public world" to be able to use it:

MessageEnqueuerClass_NewMethod.png

This modification would need an action from AQ to modify the AF. I find it backwards compatible, so no problem, but it has to be the best method to really get into the AF.

How would you do it?

What do you use for identifying an Actor?

Is there a way to implement without modifying the classes of the AF?

I also attach the modified AF for making it all clear. Please don't forget to backup your original AF folder before overwriting it (if you will do so).

Download All
0 Kudos
Message 1 of 31
(11,497 Views)

If you use "Call Chain" from within an Actor Core, you can pick out the "Actor.vi" clone that sits at the top of the call chain (or maybe it's second from the top).  The number of that clone is unique for each individual Actor, so you could use it for your integer numeric ID.  The Actor itself would have to pass this number to its Caller, as the Caller can't get this directly.  I used this technique in my prototype "Actor Manager" in the Beta forum.

Another idea to consider is flattening the Queue and using that as attribute name in a Variant-attribute-style lookup table. 

-- James

Message 2 of 31
(5,520 Views)

Thank you for the suggestions!

The call chain idea works fairly well, although I have read once that reading the call chain takes considerable ammount of time. So I tested it but it seems like that it took only 2 nanoseconds on my PC in a launched actor's actor core. I hope to get the number from the end and convert it will also not last too long - it should not.

I also tried the Variant attribute based lookup table. I guess the flattened string is too long as I could only reach about 100000 match/s. It stays around this performance for bigger array sizes like 1000, 5000, where pure Array search really gets behind. So I think the string equality check takes too long because it has too many chars.

I still would like to use my suggestion if it - or something that is as efficient - can get into the AF. If not, I would go for the Call Chain idea.

0 Kudos
Message 3 of 31
(5,520 Views)

I use the Enqueuer (previously Send Queue) as a unique ID. You can't get access to the actual number (except Flatten To String, which is hackish), but normally all you need is to test for equality against some list.

0 Kudos
Message 4 of 31
(5,520 Views)

komorbela wrote:

I still would like to use my suggestion if it - or something that is as efficient - can get into the AF. If not, I would go for the Call Chain idea.

Have you tried storing the Enqueuer in an array and the pointers in the variant attribute as suggested by powell in this thread:

http://lavag.org/topic/16079-variant-hash-table-for-aggregate-objects-dvrs-by-name/

CLA, CTA
0 Kudos
Message 5 of 31
(5,520 Views)

komorbela wrote:

I hope to get the number from the end and convert it will also not last too long - it should not.

I don't understand this statement.  The "Actor.vi" clone remains in operation until the actor shutsdown, so you can get its clone number at any point.

Never mind; I understand you now. 

So I think the string equality check takes too long because it has too many chars.

I was worried about that; it looks like its flattened form would be quite long.  You might be able to cut out the appropriate section that contains the DVR reference, but that is getting even more "hackish".

Message was edited by: drjdpowell

0 Kudos
Message 6 of 31
(5,520 Views)

drjdpowell wrote:

komorbela wrote:

I hope to get the number from the end and convert it will also not last too long - it should not.

I don't understand this statement.  The "Actor.vi" clone remains in operation until the actor shutsdown, so you can get its clone number at any point.

I only worried about get to the clone number in string and convert it to numeric. "lasts" meant time duration

By the way I implemented the first test using Clone Number and it works fine. A get clone number (to numeric type (U32)) lasts about 2,5 ns.

to AQ: I still think getting the Queue's ref would be more powerful. What do you think?

0 Kudos
Message 7 of 31
(5,520 Views)

komorbela wrote:

to AQ: I still think getting the Queue's ref would be more powerful. What do you think?

I think that would end all the queue safety and destroy one of the major points of building the framework in the first place.

Just compare the Enqueuer objects directly. Really. I promise it works great. And if you're trying to build some sort of name display, build yourself a lookup table to translate Enqueuer objects to strings.

0 Kudos
Message 8 of 31
(5,520 Views)

So to summarize what I have in my mind now:

Identifying the Actor by it's Queue is the official way to go, in harmony with the Actor Model theory. It is the so called "mail address" to it, the only ID that we have, and need to have.

If actors can send messages with zero coupled messaging, it is advantageous if the message contains the sender actor's ID. All launched actors' IDs can be stored in a list and when receiving a message with the ID in it, we can simply look up ID in the list and identify the sender actor. There are different options to achieve it. I list the options below and include a test result for the speed of the look-up operation. For every case a list of 1000 IDs is tested. The result is in match/second, so how many times can we find a randomly chosen ID from the ID list in a second.

Options for actor identifying:

1) Use the Enqueuer object and "Search 1D Array":

     -pro: easiest, straightforward, natural ID

     -con: slowest search: 20 000 match/s

2) Use the Enqueuer object and Variant Attributes style lookup table:

     -pro: easy, natural ID, close to optimal speed as ID list size grows over 20 000, but it's highly unlikely to ever handle more than 20 000 actors.

     -con: slow search(at 1000 sized ID list): 110 000 match/s

3) Use the launched actor's Actor.vi's clone number as ID. Get it from call chain, convert to U32.  Search with "Search 1D Array":

     -pro: fastest 650 000 match/s

     -con: not natural ID, this method uses an extra ID - unnecessary complexity, the clone number has to be sent by the already launched actor, so it has to be sent in a message.

4) The same as before but with Variant Attributes style lookup table:

     -pro: as ID list grows, this will be the fastest

     -con: not so fast for 1000 IDs: 270 000 match/s

5) Use the queue reference number (U32) extracted from the Enqueuer object:

     -pro: as fast as using the "Actor clone number". It is also a U32 number, so no surprise. 650 000 match/s

     -con: the Message Priority Queue class and the Message Enqueuer class of the Actor framework needs to be extended. The queue refnum is available to the user, but only as a U32 number.

6) Create one unique ID when creating the queue to the actor. Read this unique ID to identify the actors. this is only a rough idea, didn't try it yet

     -pro:should be fast, queue to actor not exposed to any extent to the user, no need for a message to get the actor's ID.

     -con: AF has to be modified, not natural ID, data size growth (but with very little amount). Not clear how to implement it exactly (to me right now )

So I have used the Enqueuer object, it works, but there are much faster methods. I still fin option 5) to be the easiest if

the user will not have access to the queue by only knowing the queue reference number.

The questions are:

What do you think about the options, is there a best way, would you do it otherways?

Can a queue be reconstructed from the U32 refnum without knowing the datatype? (I guess not, but I may not know about a trick that makes it possible...)

If the datatype is known (as it is known in case of AF) is it really a threat to AF queue safety?

To hide the RefNum away from the user an invertible transformation can be made on the U32 number. What should it be? Add a number to it? something more complicated?

Currently it is also possible to get the queue refnum for the Enqueuer object for example by using "Flatten to XML". It is only uncomfortable and unsafe, as it relies on an internal data strucutre of an object, that can change in the future.

How uncomfortable should it be for the user to get back the original queue, to confidently say that the queue safety of the Actor Framework is preserved? (for example a password protected VI which adds a constant to the U32 refnum and is not guaranteed to add the same number in the next version of LabVIEW...)

0 Kudos
Message 9 of 31
(5,520 Views)

Just a thought, but if the enqueuer class provided a method to rank two enqueuer objects (i.e greater than or less than) then one could do a binary search on a sorted array, rather than a linear search as in option (1).  This would increase speed without exposing the queue refnum and sacrificing queue safety, so perhaps AQ would allow it.

-- James

Message 10 of 31
(5,520 Views)