Personal tools
You are here: Home Members jamoma's Home BEKint jamoma's Home Namespace and messaging structure
Views

Messaging structure

  • Current implementation
  • Currently (06/2007), for technical reasons of string processing in the C++ code of jcom.hub, messages are structured as follows :
    /module.n/parameter:attribute

    where parameter can itself have several slashes in its name (ex : audio/meters/freeze)
    n in module.n stands for the instance number (module.1, module.2, etc...). A module name cannot have a slash in it
    the colon indicates that we are addressing an attribute of the parameter, the attribute can have a slash in its name (e.g. ramp/granularity/get)

    an example of a complex message can then be :
    /limiter.2/audio/gain/midi:ramp/granularity 20

    For OSC's "orthodoxy", it would be better if this message were formatted in the form :
    /limiter/2/audio/gain/midi/ramp/granularity 20

    But then it seems that it would force us to find a completely different way to handle all message management.

  • Technical reasons of this current implementation
  • Tim says :
    Specifically, we are using strchr() and strrchr() to find the first and last slash in the string (after stripping off the optional leading slash). If module names need to handle slash within them, then we can't simply use strchr() -- which is by far the fastest thing we can do. Likewise, if the subspace following a parameter is addressed using a slash instead of a colon, we cannot use strrchr() -- which also is by far the fastest solution.

    So to solve both cases, we basically need some fancier (and more expensive) string parsing. At first it could be somewhat basic. At some point we may wish to cache matches in a hashtab or something to speed this up, but I don't have a clear idea of how it would work.

    We could use Max's hashtab, or we could roll our own which would be analogous to our current linked list. If we created hashtab we could migrate the core over to it as well since it should be faster.

    Local/Global sends

  • Bottlenecks ?
  • There is a potential problem in the current implementation :
    all data is sent through the same (jcom.send jcom.remote.module.from) object
    On one hand, this is very good, because one just needs to put a global receive and retrieve one or several flows of information in a row. Also, this makes network communication very easy.
    On the other hand, working in a real (then complex) situation makes this way of doing things very likely to create big overheads.
    As a case study, let's imagine using several sensors (clocked at, say, 2 ms, like with a teabox...;-) ), and several ramps running at the same time. In this situation, we would have quite big flows of data coming out of this global receive.
    If we imagine now, with this same setup, that we want to map some of this data to several directions, thus using as much jcom.receive/jcom.oscroute pairs as we have of mapping destinations, and given that a lot of comparisons occur in jcom.oscroute, certainly that all these comparisons will create a huge overhead.

  • A first proposition by Pascal
  • A potential solution to solve both of these problems, would be to use local sends/receives for each parameter/message/return/attribute, etc...
    I guess this is not exactly the same situation now that the core is coded in C but, after having done this change in the old core, it used to speed up things by a factor 7, which is a lot !!
    Every parameter or message would have his own address (e.g. /module/parameter or /module/return). Messages received at the inlet of jcom.hub would then be sent to the appropriate jcom.receive (obtained by the concatenation of the module's name and the first element of the incoming message....).
    This would solve the overhead problem, as long as we would be avoiding all comparisons that occur in jcom.oscroute...
    And it would also solve the string parsing stuff from the current implementation, allowing then to have slashes inside of module names, as well as allowing the replacement of the colon separator for attributes by a slash, which is much more OSC-friendly...(i.e. by having a local jcom.send attached to the attribute, e.g. /module/param/attibute, instead of /module/param/attibute... does that makes sense ?)

    In this case, we would also need a feedback from the parameter, message and return to the hub, to have the info coming out of the module's command output. Maybe a jcom.remote __feedback__ could be used for that, between each parameter/messsage/return and the hub .?
    Moreover, we could use a global send in parallel, as long as we have an efficient alternative to global sends/receives, that can be used in most situations (like extensive mapping). Then, if we use a global receive on a few places, and only when necessary, it would certainly stay at a reasonnable level of overhead.

    According to Tim, though, there seemed to be a problem in this method, because of the great number of send/receive pairs. Which problem could be resolved by (drumroll...) :
  • Tim's theory on hashtabs
  • I just thought of a potential improvement to jcom.send and jcom.receive. Currently we iterate through a linked list of all jcom.receive objects looking for those with the name of the current jcom.send. Instead we could have a hashtab that contains a separate linked list for each jcom.receive name. Doing this would allow some speed increases when we use different jcom.receive names.

  • Wildcards and a second proposition by Pascal
  • Another difficulty points out in this scenario, if we want to use wildcards to match several addresses at once, since the wildcard stuff used to work precisely thanks to the global system of the current implementation.

    An hypothesis would then be to use another hash table containing linked lists of all jcom.receives for each request containing a wildcard.
    In other words :
    We have a first hash table (let's call it : the wildcard hashtab), whose keys are addresses with wildcards, and values are all the addresses that match, e.g. for key /*/audio/gain, we would have, as value the linked list : /limiter/1/audio/gain, /echo/audio/gain, output/audio/gain, etc....
    This "wildcard hashtab" would be contructed with a new element each time we encounter a new wildcard, to only have to look for all the matches the first time only.
    Then we have a second hash table (the receives hashtab), which contains, for each of these addresses, a linked list of all jcom.receives that match.

    The method for doing that could be :
    IF address contains a wildcard
    ________look for it in the wildcard hashtab
    ________IF this adress exists -> send the data to all the jcom.receives in the associated linked list (through the "receive hashtab")
    ________ELSE look for all addresses that match with this wildcard, and create a linked list with all of them, as a value for this new key
    ELSE directly go to the "receives hashtab" and send the data to the appropriate jcom.receives

  • Networking/multicasting
  • As indicated before, there seems also to be a problem with this method using local sends instead of a global one for networking
    This problem only occurs if we consider broadcasting absolutely everything to all network mates
    Having a "selective multicast", based on sending only the useful information to the concerned system only seems a much more reasonnable solution...
    In the "local sends" scenario, this could be quite easily achieved by a querying system :
    When a external system wanted to retrieve an info from our system, it would just have to query it for that adress. Then, creating (by script, for instance) a receive/prepend pair with the associated address would allow this to happen in an optimized way....

  • Algorithm clarity
  • Opinion are very likely to differ on this one :
    for big algorithms, having everything coming from an inlet and passing can be very constraigning, and can also make things a bit messy, in my opinion (Pascal)
    - moreover, using dedicated receivers (may they be jcom.receives or of another type...) would help having patches less "tree-structured", which can be useful sometimes...
    - using such dedicated receivers would also make the function of jcom.in clearer, as in the current implementation, jcom.in transmits both data coming from inside of the module (or processed trhough the module, e.g. a ramp generated by a jcom.parameter) and data coming from outside (typically control, audio or video signal). We could then remove the "connect to algorithm" output of jcom.in.... and use it only when there is an actual input (other than the command one) to the module, in the same way than jcom.out... Aliases

    new parent,

    Powered by Plone