Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Actor Framework favorite (mis?)use cases


@AristosQueue (NI) wrote:

 

Also, proving that there isn't a cycle is a hard thing. Why not start with an infrastructure that pushes back on that ever existing in the first place?

 


That I can strongly agree with, though I'm using a different infrastructure that uses different methods to discourage cycles.

0 Kudos
Message 11 of 33
(1,273 Views)

@drjdpowell wrote:


That I can strongly agree with, though I'm using a different infrastructure that uses different methods to discourage cycles.


For anyone else reading this, a bit of AF history:

jdpowell and I have largely the same goals in creating messaging systems... we were working on the same problem of "too many people build aysnch systems that are unreliable." Ne* was one of the key people helping me create the Actor Framework. Ne has nir own framework for messaging because ne opted to optimize for a different set of requirements than I did.

 

I do not insist that everyone needing async messaging use the Actor Framework. I do insist that anyone needing async messaging understand why the Actor Framework works the way it does before attempting their own! 🙂

 

* As gender is not relevant to business operations, and frequently I do not know the gender
of employees and customers that I meet online, I use these neutral pronouns for all people.
ne=he/she nem=him/her nir=his/her nirs=his/hers nemself=himself/herself

 

0 Kudos
Message 12 of 33
(1,265 Views)

Encouraging a tree dependency structure in an application's architecture is a topic that is independent of the framework being used. I wish there were more presentations about this rather than all the presentations that exist about a specific framework. The more general subject of architecture is often times independent of the framework being used.

 

I want to see a presentation that illustrates a few before/after case studies where an initial architecture with graph dependency relationships was improved by refactoring to have a tree dependency structure. If I had the examples, I'd create this presentation myself. I think it would be tremendously useful to the community.

 

I'm working on a project that uses another framework (not Actor) and I started with a tree dependency structure before I gave in and added some dependencies to reduce the number of messages bouncing back and forth in the application. DCAF exists at the low level, which isn't necessarily relevant because it's wrapped by a class called IO_Manager that acts as a gatekeeper for all hardware IO. I attached a simplified version of the UML diagram. I highlighted the two dependencies I added that broke the tree hierarchy. I resisted doing this until the frequency of hardware IO reads/writes became significant enough to warrant it.

 

If I'm understanding Steven correctly, his premise seems to be that most applications would be better designed if the dependency hierarchy was a tree structure. One of the reasons I find this so interesting is because sometimes I work with very experienced developers who make no effort to adhere to this guideline. If the guideline is so beneficial, why does it seem so few follow it?

 

Eric

0 Kudos
Message 13 of 33
(1,253 Views)

> If the guideline is so beneficial, why does it seem so few follow it?

 

Lots of reasons, many of which are reflected in this conversation already.

 

  1. "Cycles work fine for me. You just have to code them right." I think there's a lack of recognition just how much effort is being put into making them work right.
  2. "Going through the tree is too expensive in terms of performance." People first make false assumptions about how expensive messaging is up and down a tree. Then they make false assumptions about what percent of their app's time is taken in message sending. Even if up-and-down-tree is 100x the time to direct send, if the time to direct send is microseconds, 100x is irrelevant to most applications because the time is spent in the data processing loops.
  3. "I have to write a lot of message-translation code that way." Fails to recognize that they probably should be writing that code already for their module to be reusable and their application to be maintainable in the future.
  4. "I was taught to use Observer Pattern, and I've never thought about it." I mean, it's in the Gang of Four book, right? That means it has to be good, right? Sure, the Singleton Pattern gets a lot of bad press these days, but the others (22, IIRC) are still taught in school. And the UI frameworks from Microsoft, and Apple, and JAVA, and lots more are all Observer based. If so many are using it, it must be good. True... but that doesn't mean there isn't something better, especially if reason #1 applies. And, seriously, how many programmers sit around and question whether the fundamental underpinnings of computer science are weak and need fixing? I bet it is the similar ratio as the number of construction workers to structural engineers in physical buildings.
Message 14 of 33
(1,247 Views)

 


@drjdpowell wrote:

@AristosQueue (NI) wrote:

 

Also, proving that there isn't a cycle is a hard thing. Why not start with an infrastructure that pushes back on that ever existing in the first place?

 


That I can strongly agree with, though I'm using a different infrastructure that uses different methods to discourage cycles.


Since cycles can have an arbitrary number of participants ie A->B-C->D->...->A, the only way to possibly avoid coding them is to know exactly who each participant is observing and keep track of all that. That is a daunting task in a program of any real size. Not to mention that dynamic loading makes it impossible to tell who is observing who at edit time. 

 

 

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
Message 15 of 33
(1,238 Views)

I agree with you, AQ, but at the same time I sympathize with the people that break form for the reasons outlined below:

 

@AristosQueue (NI) wrote:

3. "I have to write a lot of message-translation code that way." Fails to recognize that they probably should be writing that code already for their module to be reusable and their application to be maintainable in the future.


I think this is the biggest hump, honestly.  Doing things the "right" way is seldom easy.  Writing robust, reusable code requires far more thought and foresight than just grabbing a queue or making everything public (A similar pitfall in the OOP world), and when it comes to a robust, reusable, modular messaging system?  That's tantamount to reinventing the DNS server or mailer daemon (I exaggerate, but only a little.)  I'm honestly surprised there wasn't more inbuilt support for message management in the Actor Framework itself, a la C#'s LINQ.  This ties in nicely to point 2:

 


2 ."Going through the tree is too expensive in terms of performance." People first make false assumptions about how expensive messaging is up and down a tree. Then they make false assumptions about what percent of their app's time is taken in message sending. Even if up-and-down-tree is 100x the time to direct send, if the time to direct send is microseconds, 100x is irrelevant to most applications because the time is spent in the data processing loops

And how would one go about profiling the two approaches?  By writing a lot of message-translation code. It's a catch-22, in order to decide if putting in the time to write the code needed to send a message all the way up and down the tree, you have to write the code needed to send a message all the way up and down the tree.  Again, having some sort of inbuilt class or interface (interfaces combined with an "addressed message" message child class would be amazing for this) you could just slap on the actor framework to test things, even if it doesn't support everything or support it perfectly, would make it a lot easier to win people over to the light.

 


And, seriously, how many programmers sit around and question whether the fundamental underpinnings of computer science are weak and need fixing?

Who has the time to when there's so much code to be written and work to be done?  That's what it boils down to, isn't it?  Planning good code takes time.  Writing good code takes time. Fully commenting and profiling your code--say it with me now!--takes time.  I'm thankful for what we have already, the actor framework has saved me so much time, but that third pillar of the framework, Message Transport, could definitely use more support to match its message and actor brethren.

0 Kudos
Message 16 of 33
(1,228 Views)

@m3chtroid wrote:

 Again, having some sort of inbuilt class or interface (interfaces combined with an "addressed message" message child class would be amazing for this) you could just slap on the actor framework to test things, even if it doesn't support everything or support it perfectly, would make it a lot easier to win people over to the light.

 


What would this look like? In case it's obvious from your previous post, please assume I'm not familiar with LINQ.


GCentral
0 Kudos
Message 17 of 33
(1,221 Views)

Granted, it's been a while since I've used actor framework and I'm not sure if this violates any tenents, but let's follow the postal service metaphor.  I'm imagining a child of message.lvclass named "Message Envelope" that contains a single message object and metadata about the contained message and its recipient.  (The full extent of which I'm unsure on right now.  At the very least some sort of GUID-like "postal address" string for sending to a specific actor, maybe a class identifier so that you could say "Send this to all members of the tree of this actor type or its children.  If you want to go deeper, include info about the sender so you can "bounce" messages that failed to send back to them) 

The interface would define a few VIs that would allow its members to route these messages correctly, namely:

 

  • Some way to assemble the "index".  Mostly so that each member knows the "postal addresses" and characteristics of their children (and enqueue message envelopes to them), which should be easy enough to assemble on child instantiation, as the message only needs to go up the hierarchy to ensure all parents know about their children.
  • An "Address Message.vi" that would insert the message into a Message Envelope and fill out the metadata about the recipient(s).  (Put a message envelope addressed to yourself inside a message envelope addressed to your recepient to make a self-stamped return message!)
  • Not really needed, but a "Send Message.vi" that would enqueue the envelope to its parent.
  • A "Route Addressed Message.vi" that handles Message Envelopes when received. It would automatically use the "index" to send the message to the addressed child (and if the recipient, enqueue the contained message on its own queue), or a child that matches the recipient data, and if needed (such as the specifically addressed child not being found), send it to the parent to try routing it.  This would largely be the one that needs to be overridden for message translation purposes, but at that point you'd only need to do it for specific behaviors, or to peek at the message contents, not write a routing vi for every actor.

 

...That's it, I think?  Yeah, it's open to abuse, (Self stamped return messages slightly reek of the Observer pattern) but it'd be a start, and definitely be enough to do profiling on arbitrary messages, and it's easily extensible to solve problems of the root actor being spammed like @egraham mentioned by modifying the topology of the index instead of changing the inheritance of the actors!

0 Kudos
Message 18 of 33
(1,207 Views)

> I'm imagining a child of message.lvclass named "Message Envelope" that contains

> a single message object and metadata about the contained message and its

> recipient.

 

You violated a tenant already. 🙂

How does the sender know the message recipient in order to address the message.

This is a key question.

 

In the default AF, the actor knows only about its one direct caller and its direct callees. You literally cannot write code to have anyone other than that as a recipient, and there's no need for the metadata because sender puts the message directly into the queue for the recipient.

 

In other observer/subscription systems, there's a naming system or a dynamic pattern matching system that hooks actors together or there's a common message bus and receivers check all messages that appear on the bus to claim the ones they know how to handle. And in extreme versions of this, there's some sort of path routing specification or some sort of broadcast system where you have to have metadata.

 

But the whole point of the AF design is that an actor ONLY gets messages that are meant for it. You don't write messages that are intended for some actor further than 1 step away because an actor doesn't know about those actors even existing.

 

The AF has a different postal service (queue) for every receiver. There's no metadata.

 

 

0 Kudos
Message 19 of 33
(1,188 Views)

@AristosQueue (NI) wrote:

You violated a tenant already. 🙂

How does the sender know the message recipient in order to address the message.

This is a key question.


You've activated my trap card! (I kid, I kid)

I was actually coming back to the thread specifically to point out that I very purposefully didn't mention anything about how the sender would know this message recipient, nor did I (mean to) imply that any member in the chain had any queue other than their caller and callees.  In fact, the base proposal only had recipient metadata, meaning there was no way to know if the message was sent to anybody, in keeping with the principle that messages are requests, not commands.

 

I want to reiterate, this would be a structure that would easily let a developer profile transit times and message overhead for any arbitrary form of message propagation, allowing them to quantify the (likely minimal) impact the message framework has on the program's performance! In fact, the original aside that led to me outlining this idea on the figurative back of a napkin was about how useful it'd be for profiling.  Something like that would be an invaluable tool in correcting those unfounded assumptions how "scalable" sending messages up and down the tree really is, which was what led us down this rabbit hole in your original reply!  Principles and best practices are great, but I find cold, hard, (hopefully easy to implement and test) facts are what best persuade people.

 

That said, it is a common pattern in the framework that an actor wants to send a message to its caller with the express purpose of the caller relaying that message elsewhere.  In fact, one of these is so common and important that it's already built into the framework: the Last Ack.  Oftentimes, status reports like "the temperature is 75" percolate upwards as each actor acts on that information and then reports "the temperature is 75" to its caller.  My purpose with the suggestion was not to imply that this was the correct (though often necessary) behavior, but it definitely would be able to ease the busywork of implementing "go tell your dad" messages into a framework that would at least be able to minimize the damage done by people misusing it.  Better the devil you know, and all that jazz.

0 Kudos
Message 20 of 33
(1,177 Views)