> I recall that my original one had the objects
> subscribe to specific services and then the routing object would only send
> messages to objects looking for them.

Yes, that makes sense. What I showed yesterday does much the same. You want
to avoid excessive broadcasting when the recipient is going to throw away
the message as of no interest.
>
> But in this case it sends the message to any object that subscribes and if
> the object is interested it dos whatever it needs to do. If not it
ignores it.
> So I think I’ll start with your approach this time and see how that works
> first. I think it will be more than enough.

If I catch what you're thinking about correctly, you sound inclined to make
the message broker smarter. That's a solid plan, if the extra complexity
can pay for itself. I didn't talk about this aspect of the design or even
drop in the relevant slides (they make no sense out of context.)

Backing up, the MessageHub in my example does a few things:

-- Hold service definitions and subscription data.
-- Distribute messages.

So, if a service publishes 100 messages, each subscriber gets a copy of
each of those 100 messages. This is fine in a 4D app like the one I showed.
More than fine, actually. The underlying CALL FORM/CALL WORKER
implementation seems to perform *really* well. It's very, very fast. You
can stack up ridiculous numbers and messages and 4D can then chew through
them quite quickly. I mention this as someone (I think it was Tim) said
"Hey, what about speed?" So there it is: Speed is fantastic, in my
experience.

Anyway, we've got 100 messages going to a 100 subscribers, so 10,000
messages. If you were working with a distributed/network message queue, it
would (or absolutely should) add some more smarts into the message
hub/broker/center. The main tasks remain the same:

-- Hold service definitions and subscription data.
-- Distribute messages.

..but "service and subscription data" needs to be augmented. When a
subscriber expresses interest in a service, you need a filter syntax. Say
you have a service that sends out updates every hour, but you only want
them every other hour. You might have a filter syntax that lets you say:

   Send message if hour is divisible by two.

That way, you only get half as many messages along that subscription line.
Instead of distributing copies of the message to every subscriber and
having them decide "Nah, nil interest, dump" - you move some of that logic
up into the broker. To make this work and keep the tidiness of the
design...and to make sure that "the thing knows about itself", you don't
want special-case code up in the broker. Instead, you want a generalized
expression testing language so that subscribers can inject the filter rules
and the broker can interpret the rules *abstractly* without understanding
the particulars of the service, message, or subscriber. This last point is
key. If you violate that rule, then you're messing up the clean "separation
of concerns" that divides up the publisher-broker-subscriber into the most
loosely coupled, but effectively connected arrangement. It's a trap! Don't
do it.

Yeah, that's more work. In a busy network context? It makes sense - but
those systems are dealing, sometimes, with genuinely overwhelming message
flows. Millions of messages. Saving 1% of a million is a lot - and you
could save a lot more. in the case of a one-machine 4D system? I didn't
think it would be wort the trouble.

Tip: You can get much the same result with the simpler broker design by
adding more 'services'. What I called 'services' is what is often called a
'channel'. So, you could make a channel that is itself less chatty and more
specific. You could have multiple channels so that people dial into more
exactly what they want. This is less efficient than putting filter rules in
the broker because the publisher has to send multiple messages to the
message broker, but it allows you to eliminate the excess broadcasting out
of the broker. It's not as strong a design as the smarter broker, but it's
easier, less complex and probably more than enough for any 4D-local
application.

Picking up on another question I got off-line: "You didn't really talk
about pre-emptive [thread-safe] coding at all." Correctish. I said the main
thing: CALL FORM / CALL WORKER are only peripherally connected to
multi-core programming from *our* point of view. From 4D's point of view:

-- It seems to be why they decided to add these features.
-- These features help solve some problems in pre-emptive threads for which
there was no existing, sensible option.

So, it's how they got there. So what? That's a historical note and has
nothing to do with using the commands...unless you are using them for those
very specific reasons. In those cases, yeah, the interactions and rules for
pre-emptive processing matter. Laurent E. did a decent Summit presentation
on this subject that I'd recommend watching, if you're interested. Just
note that the naive/idealized claims about the benefits of parallelization
are rarely achievable in the real world. One reason the examples are always
running nonsense calculations with no output other than screen redraws is
that it is *hard* to come up with a compelling example. (Off-loading
logging to disk files is my go to example, but there's a bit of a crashing
bug there potentially, so...) There are compute tasks that *can* be
parallelized almost ideally. Chances are they're running on your GPU, not
CPU, already. You can get some great results from mutli-core programming,
but not task/cores level improvement. Check the last slides in the set I
sent to Brent for some diagrams and references on this.
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[email protected]
**********************************************************************

Reply via email to