Limitations with v2 port implementation

We have ported a large Orocos system from v1 to v2, and identified some limitations in the v2 port implementation that we wanted to discuss with the community.

v1 ports essentially had one connection object, and thus one value. When you connected/read the port, you got the last value that was written. There was no concept of “flow” (i.e. when a connection object was updated).

v2 ports have one “object" per input/output connection, and maintain potentially different values and flow status per connection (yes, I’m simplifying here). So one output port connected to N input ports will have N connections, each with potentially different values and flow status.

We’ve run into two issues with v2 ports:

1) performance when writing to output ports is much slower in v2 than v1, as essentially the update occurs to multiple connection objects in v2 (in v1 it occurred to one connection object). One of our components has a 450% slow down when writing to its eight (8) output ports.

2) flow status does not cover the use case where you want a single connection object, and don’t care when a connection is made nor when a value is written (i.e. you don’t care about “flow”). One of our examples here is static configuration data (say the name, model or serial number, of a device, or a robot’s number of DOF). When the source component is configured or started, it writes the appropriate data to the port. If a connection is made in the future (say by a GUI, or by a reporting component that has dynamically created ports) then v2 ports will not present the value that was previously written (I believe as there has been no “flow” of data since the connection was made). In this use case, we believe that the v1 single-connection-object semantics made more sense as connected peer components are only interested in the value, and not when it was written nor whether it has been updated (i.e. they don’t care about flow).

We are *not* saying that the v2 flow status port implementation is bad, wrong or incorrect, We're simply saying that it doesn’t deal with some valid use cases. The question is, what does the community think, and what should be done about it?

Cheers
Stephen

Limitations with v2 port implementation

2015-04-08 8:08 GMT-03:00 S Roderick <kiwi [dot] net [..] ...>:
> 1) performance when writing to output ports is much slower in v2 than v1, as essentially the update occurs to multiple connection objects in v2 (in v1 it occurred to one connection object). One of our components has a 450% slow down when writing to its eight (8) output ports.
I also noticed slowdowns when a single port was connected to a lot of ports.
.
> 2) flow status does not cover the use case where you want a single connection object, and don’t care when a connection is made nor when a value is written (i.e. you don’t care about “flow”).
I would argue that if you don't care about *at all* flow, it probably
means that you want something else than a port, such as a property or
attribute. The use case you describe here reeks of attributes.

But read on.

> One of our examples here is static configuration data (say the name, model or serial number, of a device, or a robot’s number of DOF).
That is *definitely* the job of an attribute.

> When the source component is configured or started, it writes the appropriate data to the port. If a connection is made in the future (say by a GUI, or by a reporting component that has dynamically created ports) then v2 ports will not present the value that was previously written (I believe as there has been no “flow” of data since the connection was made). In this use case, we believe that the v1 single-connection-object semantics made more sense as connected peer components are only interested in the value, and not when it was written nor whether it has been updated (i.e. they don’t care about flow).

You can request getting the last value written on connection by
setting the 'init' policy to true, but that requires the output port
to keep the last written value explicitely (which is not the default
AFAIK). That's how we keep track of the current task state in Rock
(over orogen's 'state' port).

Sylvain

Limitations with v2 port implementation

On Apr 08, 2015, at 09:46, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:

> 2015-04-08 8:08 GMT-03:00 S Roderick <kiwi [dot] net [..] ...>:
>> 1) performance when writing to output ports is much slower in v2 than v1, as essentially the update occurs to multiple connection objects in v2 (in v1 it occurred to one connection object). One of our components has a 450% slow down when writing to its eight (8) output ports.
> I also noticed slowdowns when a single port was connected to a lot of ports.

Yeah, one of our systems is ~15% slower in v2 than v1. Not all of that is ports, but they are definitely contributing. :-(
.
>> 2) flow status does not cover the use case where you want a single connection object, and don’t care when a connection is made nor when a value is written (i.e. you don’t care about “flow”).
> I would argue that if you don't care about *at all* flow, it probably
> means that you want something else than a port, such as a property or
> attribute. The use case you describe here reeks of attributes.

>
> But read on.
>
>> One of our examples here is static configuration data (say the name, model or serial number, of a device, or a robot’s number of DOF).
> That is *definitely* the job of an attribute.

That is a perfectly valid alternative. But the nice thing about ports is that the deployer automagically connects components, which doesn’t happen with attributes.

We also have other use cases like this, not all of for which attributes *may* fit.

>> When the source component is configured or started, it writes the appropriate data to the port. If a connection is made in the future (say by a GUI, or by a reporting component that has dynamically created ports) then v2 ports will not present the value that was previously written (I believe as there has been no “flow” of data since the connection was made). In this use case, we believe that the v1 single-connection-object semantics made more sense as connected peer components are only interested in the value, and not when it was written nor whether it has been updated (i.e. they don’t care about flow).
>
> You can request getting the last value written on connection by
> setting the 'init' policy to true, but that requires the output port
> to keep the last written value explicitely (which is not the default
> AFAIK). That's how we keep track of the current task state in Rock
> (over orogen's 'state' port).

Agreed, but it doesn’t solve the performance issue.

Cheers
S

Limitations with v2 port implementation

> Agreed, but it doesn’t solve the performance issue.

Definitely not :(.

Just for benchmarking sake, have you done some profiling ? Or have you
tried using a lock policy instead of lock-free. Lock-free is nice, but
it looks nasty from an instruction cache p.o.v.

Sylvain

Limitations with v2 port implementation

On Wed, 8 Apr 2015, Sylvain Joyeux wrote:

>> Agreed, but it doesn’t solve the performance issue.
>
> Definitely not :(.
>
> Just for benchmarking sake, have you done some profiling ? Or have you
> tried using a lock policy instead of lock-free. Lock-free is nice, but
> it looks nasty from an instruction cache p.o.v.

Why "instruction" cache, and not just "cache" in general...?

> Sylvain

Herman

Limitations with v2 port implementation

On Apr 08, 2015, at 10:06, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:

>> Agreed, but it doesn’t solve the performance issue.
>
> Definitely not :(.
>
> Just for benchmarking sake, have you done some profiling ? Or have you
> tried using a lock policy instead of lock-free. Lock-free is nice, but
> it looks nasty from an instruction cache p.o.v.
>
> Sylvain

Benchmarking as in timing port writes? That’s where that 450% slow down comes from - we timed the function that writes the port data.

We’ve not looked at the effect of different lock policies, but I’m very reluctant to start making those kind of changes unless really necessary. And in all honesty that feels like a solution to a solution. The performance issue is fundamentally driven by the 1-to-N fanout from output ports to input ports. Certainly the locking solution may/will improve performance, but the fundamental issue remains.

Sigh … I suspect that there’s no good *and* easy answer here.

Cheers
S

Limitations with v2 port implementation

> We’ve not looked at the effect of different lock policies, but I’m very reluctant to start making those kind of changes unless really necessary. And in all honesty that feels like a solution to a solution. The performance issue is fundamentally driven by the 1-to-N fanout from output ports to input ports. Certainly the locking solution may/will improve performance, but the fundamental issue remains.

I asked because it would point to where the problem might be, *not* as
a solution to your particular problem (i.e. test the hypothesis of
"the lock free implementation is the major problem).

Just another shot in the dark: do you build with optimizations on ?

Apart from things like configuration, can you detail some other
user-cases for the original v1 behaviour ? I made the original push
for the v2 channels *because* the v1 semantic were more than awkward
(and harmful) when building our systems, so I am very curious to see
what I missed...

Sylvain

Limitations with v2 port implementation

On Apr 08, 2015, at 10:17, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:

>> We’ve not looked at the effect of different lock policies, but I’m very reluctant to start making those kind of changes unless really necessary. And in all honesty that feels like a solution to a solution. The performance issue is fundamentally driven by the 1-to-N fanout from output ports to input ports. Certainly the locking solution may/will improve performance, but the fundamental issue remains.
>
> I asked because it would point to where the problem might be, *not* as
> a solution to your particular problem (i.e. test the hypothesis of
> "the lock free implementation is the major problem).

Understood

> Just another shot in the dark: do you build with optimizations on ?

Yes. :-)

> Apart from things like configuration, can you detail some other
> user-cases for the original v1 behaviour ? I made the original push
> for the v2 channels *because* the v1 semantic were more than awkward
> (and harmful) when building our systems, so I am very curious to see
> what I missed…

I’ll put something together later for you Sylvain (gotta go for now). It’s a good discussion to have. And I don’t know that anything was really “missed”, as much as there are other equally valid ways to do things.

Cheers
S

Limitations with v2 port implementation

On Apr 08, 2015, at 10:23, S Roderick <kiwi [dot] net [..] ...> wrote:

> On Apr 08, 2015, at 10:17, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:
>
>>> We’ve not looked at the effect of different lock policies, but I’m very reluctant to start making those kind of changes unless really necessary. And in all honesty that feels like a solution to a solution. The performance issue is fundamentally driven by the 1-to-N fanout from output ports to input ports. Certainly the locking solution may/will improve performance, but the fundamental issue remains.
>>
>> I asked because it would point to where the problem might be, *not* as
>> a solution to your particular problem (i.e. test the hypothesis of
>> "the lock free implementation is the major problem).
>
> Understood
>
>> Just another shot in the dark: do you build with optimizations on ?
>
> Yes. :-)
>
>> Apart from things like configuration, can you detail some other
>> user-cases for the original v1 behaviour ? I made the original push
>> for the v2 channels *because* the v1 semantic were more than awkward
>> (and harmful) when building our systems, so I am very curious to see
>> what I missed…
>
> I’ll put something together later for you Sylvain (gotta go for now). It’s a good discussion to have. And I don’t know that anything was really “missed”, as much as there are other equally valid ways to do things.

Our system was built from the ground up using v1, including working around some of its awkward parts that the v2 ports with flow status do nicely remedy. For this discussion, I’d divide our system into four parts

1) a small number of processing pipelines (think images) for which flow status works well to "wake up” components in sequence when new data arrives. In v1 we made small coordinators to do this instead - fugly.
2) some asynchronous higher-level processing components
3) some other misc. components like logging, reporting, etc - irrelevant
4) but the majority of our system is a synchronous set of components that are woken up by a hardware signal; the appropriate computation components are sequenced by a high level coordinating supervisor; and, then new commands are sent to hardware.

Flow status ports are great for 1), largely irrelevant for 3), some times painful for 2), and nothing but trouble for 4) as a rule. The problem with 4) is that the “flow” is coordinated at the component level, not at the data level (I suspect that is one of the big differences between our systems). The motion control pipelines that are part of 4) are sequenced/coordinated by component - there was no practical concept of waking up for data arrival in v1 (ignoring EventPorts for technical reasons), so we did it this way instead. And within 4) there are a lot of fan-out and fan-in situations with multiple input-to-output ports, and in some cases, multiple-input-to-multiple-outputs - in this case individual connections are trouble.

In terms of use cases
- static configuration data, usually one output to many input
- communication between the async. components in 2) and the synch. components in 4) don’t care about flow (at a system level - remember the system semantics were designed for v1) - they just want the last value written
- multiple outputs to one input, where the outputs can be switched between on the fly. And some of the outputs are synch. while some are asynch. Here, flow status is just nasty, and we’ve had to add a bunch of explicit clear calls, and the like, into our system to effectively flush (or similar) all data when certain mode switches occur. Because the upstream components are coordinated, we only want the last value written (which is, by definition, from the last component executed)
- performance - some of our systems run really close to deadline, and the extra few % of updating multiple connection objects is too much.

In a more theoretical sense, our components were (mostly) written to push the responsibility of when and whom wrote input data up to a higher level (i.e. a coordinator). They all depend on a “I just want the last/latest value available on my input port” mentality. I still maintain that this is valid, even with v2 flow ports, as it decouples the inside of the component from any other components, and puts the responsibility for coordination on the system designer. In reality, we’ve now in v2 got a lot more coupling of the inside of our components with other peer components, because v2 ports (in *some* ways) require that the end user be more aware of when and whom wrote data. Again, v2 ports are just different - I’m not saying they’re good, bad, or broken.

What I don’t want to get into here is a lot of “well just redesign your system to …” kind of discussion. We have a large system with a lot of legacy in its architecture and design. No doubt, if we were to re-design from scratch with only v2 in mind we’d come up with a different result. What I’m hoping for here is discussion on the general concept of whether the v2 port implementation (flow status with a connection object per input/output combination) solves the general use cases that we inherited from v1, and which I still feel are equally as valid as using flow status type ports.

Hope this helps, Sylvain (and everyone else).

HTH
S

Limitations with v2 port implementation

> - multiple outputs to one input, where the outputs can be switched between on the fly. And some of the outputs are synch. while some are asynch. Here, flow status is just nasty, and we’ve had to add a bunch of explicit clear calls, and the like, into our system to effectively flush (or similar) all data when certain mode switches occur. Because the upstream components are coordinated, we only want the last value written (which is, by definition, from the last component executed)

Basically, this is broken because samples are not gathered per-port,
but per-channel. Which means that RTT v2 ports don't have a concept of
"last value written to the port", only "last value written to the
channel". Which is something most people "ignore" because the issue
happens only during the transition (so it is most of the time "hidden"
when the ports have high data rates). It is an interesting issue. It
arises as soon as one wants to do RT-compatible switching (where
disconnecting and reconnecting Syskit-style is not possible) in a
clean way.

I personally think that it could make sense to go for a per-input-port
buffer element, but then a bunch of other configuration problems occur
(as e.g. you need to size the buffers to accomodate any configuration,
not only the configuration you have right now, plus it gets weird when
pulling is involved)

> - performance - some of our systems run really close to deadline, and the extra few % of updating multiple connection objects is too much.
I would really like to investigate the performance issue there
further, but I really don't have time for that.

> In reality, we’ve now in v2 got a lot more coupling of the inside of our components with other peer components, because v2 ports (in *some* ways) require that the end user be more aware of when and whom wrote data.
While I don't dispute that it is your experience migrating from v1, I
really personally did not see that so far in systems I was involved
with. And I am very very careful about keeping components insulated
(i.e. not putting any system concerns in the component implementation)

Anyways, to summarize my understanding of the problems you highlight
with v2 ports:
- multiple output, single input connections, in architectures where
the output components are begin "switched" (i.e. there's only one
active at a time), and where the input only wants the last value (not
all values written). In v2, values are read out-of-order. In effect, a
'data' connection in v2 becomes an out-of-order buffer where each
channel has one slot in the buffer.
- performance

Limitations with v2 port implementation

On Apr 08, 2015, at 14:07, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:

>> - multiple outputs to one input, where the outputs can be switched between on the fly. And some of the outputs are synch. while some are asynch. Here, flow status is just nasty, and we’ve had to add a bunch of explicit clear calls, and the like, into our system to effectively flush (or similar) all data when certain mode switches occur. Because the upstream components are coordinated, we only want the last value written (which is, by definition, from the last component executed)
>
> Basically, this is broken because samples are not gathered per-port,
> but per-channel. Which means that RTT v2 ports don't have a concept of
> "last value written to the port", only "last value written to the
> channel". Which is something most people "ignore" because the issue
> happens only during the transition (so it is most of the time "hidden"
> when the ports have high data rates). It is an interesting issue. It
> arises as soon as one wants to do RT-compatible switching (where
> disconnecting and reconnecting Syskit-style is not possible) in a
> clean way.

What is “broken” here Sylvain? It isn’t clear what you mean.

> I personally think that it could make sense to go for a per-input-port
> buffer element, but then a bunch of other configuration problems occur
> (as e.g. you need to size the buffers to accomodate any configuration,
> not only the configuration you have right now, plus it gets weird when
> pulling is involved)
>
>> - performance - some of our systems run really close to deadline, and the extra few % of updating multiple connection objects is too much.
> I would really like to investigate the performance issue there
> further, but I really don't have time for that.

Fair enough. Neither do we in reality. But I think we can probably agree that the fundamental difference between 8 output ports updating 8 connection objects (ala v1), vs 8 output ports updating 40 connection objects (ala v2) (I’d guess that we’re 5-to-1 or similar in this case) is always going to be worse performance wise.

>> In reality, we’ve now in v2 got a lot more coupling of the inside of our components with other peer components, because v2 ports (in *some* ways) require that the end user be more aware of when and whom wrote data.
> While I don't dispute that it is your experience migrating from v1, I
> really personally did not see that so far in systems I was involved
> with. And I am very very careful about keeping components insulated
> (i.e. not putting any system concerns in the component implementation)

Different, not better or worse. :-)

> Anyways, to summarize my understanding of the problems you highlight
> with v2 ports:
> - multiple output, single input connections, in architectures where
> the output components are begin "switched" (i.e. there's only one
> active at a time), and where the input only wants the last value (not
> all values written). In v2, values are read out-of-order. In effect, a
> 'data' connection in v2 becomes an out-of-order buffer where each
> channel has one slot in the buffer.
> - performance

That seems like a pretty good summary of my off-the-top-of-my-head list of use cases.
S

Limitations with v2 port implementation

2015-04-08 15:17 GMT-03:00 S Roderick <kiwi [dot] net [..] ...>:
> On Apr 08, 2015, at 14:07, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:
>
>>> - multiple outputs to one input, where the outputs can be switched between on the fly. And some of the outputs are synch. while some are asynch. Here, flow status is just nasty, and we’ve had to add a bunch of explicit clear calls, and the like, into our system to effectively flush (or similar) all data when certain mode switches occur. Because the upstream components are coordinated, we only want the last value written (which is, by definition, from the last component executed)
>>
>> Basically, this is broken because samples are not gathered per-port,
>> but per-channel. Which means that RTT v2 ports don't have a concept of
>> "last value written to the port", only "last value written to the
>> channel". Which is something most people "ignore" because the issue
>> happens only during the transition (so it is most of the time "hidden"
>> when the ports have high data rates). It is an interesting issue. It
>> arises as soon as one wants to do RT-compatible switching (where
>> disconnecting and reconnecting Syskit-style is not possible) in a
>> clean way.
>
> What is “broken” here Sylvain? It isn’t clear what you mean.

I meant: your system (which, I agree, is architectured in a valid way)
is broken by migrating to v2 ports.

> Fair enough. Neither do we in reality. But I think we can probably agree that the fundamental difference between 8 output ports updating 8 connection objects (ala v1), vs 8 output ports updating 40 connection objects (ala v2) (I’d guess that we’re 5-to-1 or similar in this case) is always going to be worse performance wise.

Yes. Except that it is my opinion that reading and writing to ports
should be low-overhead enough that you would not notice. Unless you
have MB-sized structures, or very very low processing power that is.
There's a lot of overhead in connections, currently, that should not
be there (like a fuckload of mutexes). Moreover, I personally suspect
that the port performance grows faster than linear when the number of
connections grow (from some really really bad performance I got when
creating a lot of connections to a single port). Never benchmarked,
but that's a hunch I have.

>>> In reality, we’ve now in v2 got a lot more coupling of the inside of our components with other peer components, because v2 ports (in *some* ways) require that the end user be more aware of when and whom wrote data.
>> While I don't dispute that it is your experience migrating from v1, I
>> really personally did not see that so far in systems I was involved
>> with. And I am very very careful about keeping components insulated
>> (i.e. not putting any system concerns in the component implementation)
>
> Different, not better or worse. :-)

I was really reacting on "v2 ports (in *some* ways) require that the
end user be more aware of when and whom wrote data.". That's something
I did not experience *at all*. I had a lot more trouble with v1 in
that respect (which is why I scratched my itch and designed the
channel-based connections). But that's out of the main topic.

Sylvain

Limitations with v2 port implementation

On Apr 08, 2015, at 14:47, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:

> 2015-04-08 15:17 GMT-03:00 S Roderick <kiwi [dot] net [..] ...>:
>> On Apr 08, 2015, at 14:07, Sylvain Joyeux <sylvain [dot] joyeux [..] ...> wrote:
>>
>>>> - multiple outputs to one input, where the outputs can be switched between on the fly. And some of the outputs are synch. while some are asynch. Here, flow status is just nasty, and we’ve had to add a bunch of explicit clear calls, and the like, into our system to effectively flush (or similar) all data when certain mode switches occur. Because the upstream components are coordinated, we only want the last value written (which is, by definition, from the last component executed)
>>>
>>> Basically, this is broken because samples are not gathered per-port,
>>> but per-channel. Which means that RTT v2 ports don't have a concept of
>>> "last value written to the port", only "last value written to the
>>> channel". Which is something most people "ignore" because the issue
>>> happens only during the transition (so it is most of the time "hidden"
>>> when the ports have high data rates). It is an interesting issue. It
>>> arises as soon as one wants to do RT-compatible switching (where
>>> disconnecting and reconnecting Syskit-style is not possible) in a
>>> clean way.
>>
>> What is “broken” here Sylvain? It isn’t clear what you mean.
>
> I meant: your system (which, I agree, is architectured in a valid way)
> is broken by migrating to v2 ports.

Yep! We got it to work, but it was *much* harder than anyone expected.

>> Fair enough. Neither do we in reality. But I think we can probably agree that the fundamental difference between 8 output ports updating 8 connection objects (ala v1), vs 8 output ports updating 40 connection objects (ala v2) (I’d guess that we’re 5-to-1 or similar in this case) is always going to be worse performance wise.
>
> Yes. Except that it is my opinion that reading and writing to ports
> should be low-overhead enough that you would not notice. Unless you
> have MB-sized structures, or very very low processing power that is.
> There's a lot of overhead in connections, currently, that should not
> be there (like a fuckload of mutexes). Moreover, I personally suspect
> that the port performance grows faster than linear when the number of
> connections grow (from some really really bad performance I got when
> creating a lot of connections to a single port). Never benchmarked,
> but that's a hunch I have.

Those 8 ports we measured total maybe 50 doubles. We’re actually only talking 10’s of microseconds of difference, so not big numbers. But we have a *lot* of ports (remember, few struct's due v1 toolkits!) and even that ~4x difference may add up. Actually, our simplest system configuration has ~700 connections between ports, so maybe 200 to 300 actual ports ...

Cheers
S

Limitations with v2 port implementation

Hey,
there is another issue with the current port implementation,
it might be related. The current implementation always searches
all known connections in a linear way and returns the first one
that has a sample. This is bad for runtime issues, and (even if this
is more theoretical) bad in terms of starvation. What I mean is,
if the sample take a lot of time to be processed between read
calls, so that new samples arrive in between on the first connections,
the last connections will never be read.
Perhaps adding some sort of clock hand algorithm helps here.
Greetings
Janosch

Ruben Smits's picture

Limitations with v2 port implementation

On Wed, Apr 8, 2015 at 1:08 PM, S Roderick <kiwi [dot] net [..] ...> wrote:

> We have ported a large Orocos system from v1 to v2, and identified some
> limitations in the v2 port implementation that we wanted to discuss with
> the community.
>
> v1 ports essentially had one connection object, and thus one value. When
> you connected/read the port, you got the last value that was written. There
> was no concept of “flow” (i.e. when a connection object was updated).
>
> v2 ports have one “object" per input/output connection, and maintain
> potentially different values and flow status per connection (yes, I’m
> simplifying here). So one output port connected to N input ports will have
> N connections, each with potentially different values and flow status.
>
> We’ve run into two issues with v2 ports:
>
> 1) performance when writing to output ports is much slower in v2 than v1,
> as essentially the update occurs to multiple connection objects in v2 (in
> v1 it occurred to one connection object). One of our components has a 450%
> slow down when writing to its eight (8) output ports.
>
> 2) flow status does not cover the use case where you want a single
> connection object, and don’t care when a connection is made nor when a
> value is written (i.e. you don’t care about “flow”). One of our examples
> here is static configuration data (say the name, model or serial number, of
> a device, or a robot’s number of DOF). When the source component is
> configured or started, it writes the appropriate data to the port. If a
> connection is made in the future (say by a GUI, or by a reporting component
> that has dynamically created ports) then v2 ports will not present the
> value that was previously written (I believe as there has been no “flow” of
> data since the connection was made). In this use case, we believe that the
> v1 single-connection-object semantics made more sense as connected peer
> components are only interested in the value, and not when it was written
> nor whether it has been updated (i.e. they don’t care about flow).
>

AFAIK, you can have 2) working in v2 if you create the connection using the
init flag set to true:
http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_...
and a have a writer with keepLastWrittenValue to true.

R.

>
> We are *not* saying that the v2 flow status port implementation is bad,
> wrong or incorrect, We're simply saying that it doesn’t deal with some
> valid use cases. The question is, what does the community think, and what
> should be done about it?
>
> Cheers
> Stephen
> --
> Orocos-Dev mailing list
> Orocos-Dev [..] ...
> http://lists.mech.kuleuven.be/mailman/listinfo/orocos-dev
>

Limitations with v2 port implementation

On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...> wrote:

>
>
> On Wed, Apr 8, 2015 at 1:08 PM, S Roderick <kiwi [dot] net [..] ...> wrote:
> We have ported a large Orocos system from v1 to v2, and identified some limitations in the v2 port implementation that we wanted to discuss with the community.
>
> v1 ports essentially had one connection object, and thus one value. When you connected/read the port, you got the last value that was written. There was no concept of “flow” (i.e. when a connection object was updated).
>
> v2 ports have one “object" per input/output connection, and maintain potentially different values and flow status per connection (yes, I’m simplifying here). So one output port connected to N input ports will have N connections, each with potentially different values and flow status.
>
> We’ve run into two issues with v2 ports:
>
> 1) performance when writing to output ports is much slower in v2 than v1, as essentially the update occurs to multiple connection objects in v2 (in v1 it occurred to one connection object). One of our components has a 450% slow down when writing to its eight (8) output ports.
>
> 2) flow status does not cover the use case where you want a single connection object, and don’t care when a connection is made nor when a value is written (i.e. you don’t care about “flow”). One of our examples here is static configuration data (say the name, model or serial number, of a device, or a robot’s number of DOF). When the source component is configured or started, it writes the appropriate data to the port. If a connection is made in the future (say by a GUI, or by a reporting component that has dynamically created ports) then v2 ports will not present the value that was previously written (I believe as there has been no “flow” of data since the connection was made). In this use case, we believe that the v1 single-connection-object semantics made more sense as connected peer components are only interested in the value, and not when it was written nor whether it has been updated (i.e. they don’t care about flow).
>
> AFAIK, you can have 2) working in v2 if you create the connection using the init flag set to true: http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_... and a have a writer with keepLastWrittenValue to true.

I don’t think that that solves the whole issue. You still have multiple connections => performance hit. Also, didn’t we find a thread-safety issue with that approach?
S

>
> R.
>
>
> We are *not* saying that the v2 flow status port implementation is bad, wrong or incorrect, We're simply saying that it doesn’t deal with some valid use cases. The question is, what does the community think, and what should be done about it?
>
> Cheers
> Stephen

Limitations with v2 port implementation

On Wed, 8 Apr 2015, S Roderick wrote:

> On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...> wrote:
>
> On Wed, Apr 8, 2015 at 1:08 PM, S Roderick <kiwi [dot] net [..] ...> wrote:
> We have ported a large Orocos system from v1 to v2, and identified some
> limitations in the v2 port implementation that we wanted to discuss with
> the community.
>
> v1 ports essentially had one connection object, and thus one value. When
> you connected/read the port, you got the last value that was written.
> There was no concept of “flow” (i.e. when a connection object was
> updated).
>
> v2 ports have one “object" per input/output connection, and maintain
> potentially different values and flow status per connection (yes, I’m
> simplifying here). So one output port connected to N input ports will
> have N connections, each with potentially different values and flow
> status.
>
> We’ve run into two issues with v2 ports:
>
> 1) performance when writing to output ports is much slower in v2 than
> v1, as essentially the update occurs to multiple connection objects in
> v2 (in v1 it occurred to one connection object). One of our components
> has a 450% slow down when writing to its eight (8) output ports.
>
> 2) flow status does not cover the use case where you want a single
> connection object, and don’t care when a connection is made nor when a
> value is written (i.e. you don’t care about “flow”). One of our examples
> here is static configuration data (say the name, model or serial number,
> of a device, or a robot’s number of DOF). When the source component is
> configured or started, it writes the appropriate data to the port. If a
> connection is made in the future (say by a GUI, or by a reporting
> component that has dynamically created ports) then v2 ports will not
> present the value that was previously written (I believe as there has
> been no “flow” of data since the connection was made). In this use case,
> we believe that the v1 single-connection-object semantics made more
> sense as connected peer components are only interested in the value, and
> not when it was written nor whether it has been updated (i.e. they don’t
> care about flow).
>
>
> AFAIK, you can have 2) working in v2 if you create the connection using the init flag set
> totrue: http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_1ConnPolicy.html#
> a5da839ba68d6ff35ddc44171562ed356 and a have a writer with keepLastWrittenValue to true.

We made a mistake in the original RTT design by providing too many
configuration options. This is not a problem if every configuration
leads to a unique feature, but it does become a problem if different
configurations can provide the same feature. An example is the
"difference" between properties and attributes, or events and data.
So, while you are probably right, I still think this is not the Right
Way to go.

> I don’t think that that solves the whole issue. You still have multiple connections =>
> performance hit. Also, didn’t we find a thread-safety issue with that approach?

Both problems are _communication_ related, so should be solved in the
_communication_ middleware... Select one that is minimal and does one
thing right (ZeroMQ? nanomsg?) and has an eye for performance. I would
now strip RTT to a pure realtime "container", that is, a "computation
only" version of the Linux or Solaris containers. Again, trying to do
one thing right.

(BTW what I describe above is already Work In Progress in our group; for
way too long, because of a lack of development power...)

> S

Herman

Limitations with v2 port implementation

On Apr 08, 2015, at 09:41, Herman Bruyninckx <Herman [dot] Bruyninckx [..] ...> wrote:

> On Wed, 8 Apr 2015, S Roderick wrote:
>
>> On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...> wrote:
>>
>> On Wed, Apr 8, 2015 at 1:08 PM, S Roderick <kiwi [dot] net [..] ...> wrote:
>> We have ported a large Orocos system from v1 to v2, and identified some
>> limitations in the v2 port implementation that we wanted to discuss with
>> the community.
>>
>> v1 ports essentially had one connection object, and thus one value. When
>> you connected/read the port, you got the last value that was written.
>> There was no concept of “flow” (i.e. when a connection object was
>> updated).
>>
>> v2 ports have one “object" per input/output connection, and maintain
>> potentially different values and flow status per connection (yes, I’m
>> simplifying here). So one output port connected to N input ports will
>> have N connections, each with potentially different values and flow
>> status.
>>
>> We’ve run into two issues with v2 ports:
>>
>> 1) performance when writing to output ports is much slower in v2 than
>> v1, as essentially the update occurs to multiple connection objects in
>> v2 (in v1 it occurred to one connection object). One of our components
>> has a 450% slow down when writing to its eight (8) output ports.
>>
>> 2) flow status does not cover the use case where you want a single
>> connection object, and don’t care when a connection is made nor when a
>> value is written (i.e. you don’t care about “flow”). One of our examples
>> here is static configuration data (say the name, model or serial number,
>> of a device, or a robot’s number of DOF). When the source component is
>> configured or started, it writes the appropriate data to the port. If a
>> connection is made in the future (say by a GUI, or by a reporting
>> component that has dynamically created ports) then v2 ports will not
>> present the value that was previously written (I believe as there has
>> been no “flow” of data since the connection was made). In this use case,
>> we believe that the v1 single-connection-object semantics made more
>> sense as connected peer components are only interested in the value, and
>> not when it was written nor whether it has been updated (i.e. they don’t
>> care about flow).
>> AFAIK, you can have 2) working in v2 if you create the connection using the init flag set
>> totrue: http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_...
>> a5da839ba68d6ff35ddc44171562ed356 and a have a writer with keepLastWrittenValue to true.
>
> We made a mistake in the original RTT design by providing too many
> configuration options. This is not a problem if every configuration
> leads to a unique feature, but it does become a problem if different
> configurations can provide the same feature. An example is the
> "difference" between properties and attributes, or events and data.
> So, while you are probably right, I still think this is not the Right
> Way to go.

I disagree with some of this. Properties and attributes are very similar concepts, and it can be difficult to choose one over the other. But events and data are quite different for us. Events (to us) are much more a state machine primitive - Data is stuff you move between components. Yes, the two can be used interchangeably, but the removal of the Event primitive in v2 was a huge mistake IMHO. I’m sure that some of you won’t agree … shrug.

>> I don’t think that that solves the whole issue. You still have multiple connections =>
>> performance hit. Also, didn’t we find a thread-safety issue with that approach?
>
> Both problems are _communication_ related, so should be solved in the
> _communication_ middleware... Select one that is minimal and does one
> thing right (ZeroMQ? nanomsg?) and has an eye for performance. I would
> now strip RTT to a pure realtime "container", that is, a "computation
> only" version of the Linux or Solaris containers. Again, trying to do
> one thing right.

That’s one point of view. I still maintain that the Orocos v1 and v2 do a pretty damn good job for what they’re designed for. Yes, we’d all like some things done differently, but it’s still a very usable system as is.

YMMV
S

Limitations with v2 port implementation

On Wed, 8 Apr 2015, S Roderick wrote:

> On Apr 08, 2015, at 09:41, Herman Bruyninckx <Herman [dot] Bruyninckx [..] ...> wrote:
>
> On Wed, 8 Apr 2015, S Roderick wrote:
>
> On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...>
> wrote:
>
>      On Wed, Apr 8, 2015 at 1:08 PM, S
> Roderick <kiwi [dot] net [..] ...> wrote:
>            We have ported a large Orocos system from v1 to v2, and
> identified some
>            limitations in the v2 port implementation that we wanted to
> discuss with
>            the community.
>
>            v1 ports essentially had one connection object, and thus one
> value. When
>            you connected/read the port, you got the last value that was
> written.
>            There was no concept of “flow” (i.e. when a connection object
> was
>            updated).
>
>            v2 ports have one “object" per input/output connection, and
> maintain
>            potentially different values and flow status per connection
> (yes, I’m
>            simplifying here). So one output port connected to N input
> ports will
>            have N connections, each with potentially different values
> and flow
>            status.
>
>            We’ve run into two issues with v2 ports:
>
>            1) performance when writing to output ports is much slower in
> v2 than
>            v1, as essentially the update occurs to multiple connection
> objects in
>            v2 (in v1 it occurred to one connection object). One of our
> components
>            has a 450% slow down when writing to its eight (8) output
> ports.
>
>            2) flow status does not cover the use case where you want a
> single
>            connection object, and don’t care when a connection is made
> nor when a
>            value is written (i.e. you don’t care about “flow”). One of
> our examples
>            here is static configuration data (say the name, model or
> serial number,
>            of a device, or a robot’s number of DOF). When the source
> component is
>            configured or started, it writes the appropriate data to the
> port. If a
>            connection is made in the future (say by a GUI, or by a
> reporting
>            component that has dynamically created ports) then v2 ports
> will not
>            present the value that was previously written (I believe as
> there has
>            been no “flow” of data since the connection was made). In
> this use case,
>            we believe that the v1 single-connection-object semantics
> made more
>            sense as connected peer components are only interested in the
> value, and
>            not when it was written nor whether it has been updated (i.e.
> they don’t
>            care about flow).
> AFAIK, you can have 2) working in v2 if you create the connection using
> the init flag set
> totrue: http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_1ConnPolicy.htm
> l#
> a5da839ba68d6ff35ddc44171562ed356 and a have a writer with
> keepLastWrittenValue to true.
>
>
> We made a mistake in the original RTT design by providing too many
> configuration options. This is not a problem if every configuration
> leads to a unique feature, but it does become a problem if different
> configurations can provide the same feature. An example is the
> "difference" between properties and attributes, or events and data.
> So, while you are probably right, I still think this is not the Right
> Way to go.
>
>
> I disagree with some of this. Properties and attributes are very similar concepts, and it can be
> difficult to choose one over the other. But events and data are quite different for us. Events
> (to us) are much more a state machine primitive - Data is stuff you move between components.

This is a _semantic_ difference, and an important one. But RTT should
have provided only _mechanism_; in the code, both events and data flows
are treated very similar; the only difference happen to be in the
_communication_ policies (e.g., different ways to throw away messages).

> Yes, the two can be used interchangeably, but the removal of the Event primitive in v2 was a
> huge mistake IMHO. I’m sure that some of you won’t agree … shrug.
>  
> I don’t think that that solves the whole issue. You still have multiple
> connections =>
> performance hit. Also, didn’t we find a thread-safety issue with that
> approach?
>
> Both problems are _communication_ related, so should be solved in the
> _communication_ middleware... Select one that is minimal and does one
> thing right (ZeroMQ? nanomsg?) and has an eye for performance. I would
> now strip RTT to a pure realtime "container", that is, a "computation
> only" version of the Linux or Solaris containers. Again, trying to do
> one thing right.
>
> That’s one point of view. I still maintain that the Orocos v1 and v2 do a pretty damn good job
> for what they’re designed for.

Performance wise and configuration wise, I agree! :-)
But too many people are scared away by the lack of clarity of what of
its features to use exactly why and when. A good example is the ongoing
discussion of the new user who wants to connect a GUI to realtime.

> Yes, we’d all like some things done differently, but it’s still a
> very usable system as is.

For experts, it's (still) the best! :-) But the same can be achieved
with less effort and code... (Hindsight, you know....)

> YMMV
> S

Herman

Limitations with v2 port implementation

On Apr 08, 2015, at 10:09, Herman Bruyninckx <Herman [dot] Bruyninckx [..] ...> wrote:

> On Wed, 8 Apr 2015, S Roderick wrote:
>
>> On Apr 08, 2015, at 09:41, Herman Bruyninckx <Herman [dot] Bruyninckx [..] ...> wrote:
>>
>> On Wed, 8 Apr 2015, S Roderick wrote:
>>
>> On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...>
>> wrote:
>>
>> On Wed, Apr 8, 2015 at 1:08 PM, S
>> Roderick <kiwi [dot] net [..] ...> wrote:
>> We have ported a large Orocos system from v1 to v2, and
>> identified some
>> limitations in the v2 port implementation that we wanted to
>> discuss with
>> the community.
>>
>> v1 ports essentially had one connection object, and thus one
>> value. When
>> you connected/read the port, you got the last value that was
>> written.
>> There was no concept of “flow” (i.e. when a connection object
>> was
>> updated).
>>
>> v2 ports have one “object" per input/output connection, and
>> maintain
>> potentially different values and flow status per connection
>> (yes, I’m
>> simplifying here). So one output port connected to N input
>> ports will
>> have N connections, each with potentially different values
>> and flow
>> status.
>>
>> We’ve run into two issues with v2 ports:
>>
>> 1) performance when writing to output ports is much slower in
>> v2 than
>> v1, as essentially the update occurs to multiple connection
>> objects in
>> v2 (in v1 it occurred to one connection object). One of our
>> components
>> has a 450% slow down when writing to its eight (8) output
>> ports.
>>
>> 2) flow status does not cover the use case where you want a
>> single
>> connection object, and don’t care when a connection is made
>> nor when a
>> value is written (i.e. you don’t care about “flow”). One of
>> our examples
>> here is static configuration data (say the name, model or
>> serial number,
>> of a device, or a robot’s number of DOF). When the source
>> component is
>> configured or started, it writes the appropriate data to the
>> port. If a
>> connection is made in the future (say by a GUI, or by a
>> reporting
>> component that has dynamically created ports) then v2 ports
>> will not
>> present the value that was previously written (I believe as
>> there has
>> been no “flow” of data since the connection was made). In
>> this use case,
>> we believe that the v1 single-connection-object semantics
>> made more
>> sense as connected peer components are only interested in the
>> value, and
>> not when it was written nor whether it has been updated (i.e.
>> they don’t
>> care about flow).
>> AFAIK, you can have 2) working in v2 if you create the connection using
>> the init flag set
>> totrue: http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_...
>> l#
>> a5da839ba68d6ff35ddc44171562ed356 and a have a writer with
>> keepLastWrittenValue to true.
>>
>> We made a mistake in the original RTT design by providing too many
>> configuration options. This is not a problem if every configuration
>> leads to a unique feature, but it does become a problem if different
>> configurations can provide the same feature. An example is the
>> "difference" between properties and attributes, or events and data.
>> So, while you are probably right, I still think this is not the Right
>> Way to go.
>> I disagree with some of this. Properties and attributes are very similar concepts, and it can be
>> difficult to choose one over the other. But events and data are quite different for us. Events
>> (to us) are much more a state machine primitive - Data is stuff you move between components.
>
> This is a _semantic_ difference, and an important one. But RTT should
> have provided only _mechanism_; in the code, both events and data flows
> are treated very similar; the only difference happen to be in the
> _communication_ policies (e.g., different ways to throw away messages).
>
>> Yes, the two can be used interchangeably, but the removal of the Event primitive in v2 was a
>> huge mistake IMHO. I’m sure that some of you won’t agree … shrug.
>>
>> I don’t think that that solves the whole issue. You still have multiple
>> connections =>
>> performance hit. Also, didn’t we find a thread-safety issue with that
>> approach?
>>
>> Both problems are _communication_ related, so should be solved in the
>> _communication_ middleware... Select one that is minimal and does one
>> thing right (ZeroMQ? nanomsg?) and has an eye for performance. I would
>> now strip RTT to a pure realtime "container", that is, a "computation
>> only" version of the Linux or Solaris containers. Again, trying to do
>> one thing right.
>> That’s one point of view. I still maintain that the Orocos v1 and v2 do a pretty damn good job
>> for what they’re designed for.
>
> Performance wise and configuration wise, I agree! :-)
> But too many people are scared away by the lack of clarity of what of
> its features to use exactly why and when. A good example is the ongoing
> discussion of the new user who wants to connect a GUI to realtime.

Disagree Herman. That’s the same user (not developer) documentation issue that has plagued Orocos since the beginning. It’s not the primitives he’s struggling with - it’s a lack of documentation on how to use the entire framework. But this is off topic.

>> Yes, we’d all like some things done differently, but it’s still a
>> very usable system as is.
>
> For experts, it's (still) the best! :-) But the same can be achieved
> with less effort and code... (Hindsight, you know….)

YMMV
S

Limitations with v2 port implementation

> We made a mistake in the original RTT design by providing too many
> configuration options. This is not a problem if every configuration
> leads to a unique feature, but it does become a problem if different
> configurations can provide the same feature. An example is the
> "difference" between properties and attributes
Funnily enough, I've made my mind to use properties for setting
configuration from the system management to the components, and
attributes to report configuration from the component to the outside
world.

Sylvain

Limitations with v2 port implementation

On Wed, 8 Apr 2015, Sylvain Joyeux wrote:

>> We made a mistake in the original RTT design by providing too many
>> configuration options. This is not a problem if every configuration
>> leads to a unique feature, but it does become a problem if different
>> configurations can provide the same feature. An example is the
>> "difference" between properties and attributes
> Funnily enough, I've made my mind to use properties for setting
> configuration from the system management to the components, and
> attributes to report configuration from the component to the outside
> world.

That usage corresponds to the _opposite_ of the original semantics that
we had in mind 15 years ago. Inspired by the linguistic semantics that a
"property" is something one "has", and an "attribute" is something one
"gets" :-)

Anyway, semantic interpretation of the same mechanism should not be done
inside the library but in the (model-based, application-centric) tools
that make use of it.

> Sylvain

Herman

Ruben Smits's picture

Limitations with v2 port implementation

On Wed, Apr 8, 2015 at 3:32 PM, S Roderick <kiwi [dot] net [..] ...> wrote:

> On Apr 08, 2015, at 09:25, Ruben Smits <ruben [dot] smits [..] ...>
> wrote:
>
>
>
> On Wed, Apr 8, 2015 at 1:08 PM, S Roderick <kiwi [dot] net [..] ...> wrote:
>
>> We have ported a large Orocos system from v1 to v2, and identified some
>> limitations in the v2 port implementation that we wanted to discuss with
>> the community.
>>
>> v1 ports essentially had one connection object, and thus one value. When
>> you connected/read the port, you got the last value that was written. There
>> was no concept of “flow” (i.e. when a connection object was updated).
>>
>> v2 ports have one “object" per input/output connection, and maintain
>> potentially different values and flow status per connection (yes, I’m
>> simplifying here). So one output port connected to N input ports will have
>> N connections, each with potentially different values and flow status.
>>
>> We’ve run into two issues with v2 ports:
>>
>> 1) performance when writing to output ports is much slower in v2 than v1,
>> as essentially the update occurs to multiple connection objects in v2 (in
>> v1 it occurred to one connection object). One of our components has a 450%
>> slow down when writing to its eight (8) output ports.
>>
>> 2) flow status does not cover the use case where you want a single
>> connection object, and don’t care when a connection is made nor when a
>> value is written (i.e. you don’t care about “flow”). One of our examples
>> here is static configuration data (say the name, model or serial number, of
>> a device, or a robot’s number of DOF). When the source component is
>> configured or started, it writes the appropriate data to the port. If a
>> connection is made in the future (say by a GUI, or by a reporting component
>> that has dynamically created ports) then v2 ports will not present the
>> value that was previously written (I believe as there has been no “flow” of
>> data since the connection was made). In this use case, we believe that the
>> v1 single-connection-object semantics made more sense as connected peer
>> components are only interested in the value, and not when it was written
>> nor whether it has been updated (i.e. they don’t care about flow).
>>
>
> AFAIK, you can have 2) working in v2 if you create the connection using
> the init flag set to true:
> http://www.orocos.org/stable/documentation/rtt/v2.x/api/html/classRTT_1_...
> and a have a writer with keepLastWrittenValue to true.
>
>
> I don’t think that that solves the whole issue. You still have multiple
> connections => performance hit. Also, didn’t we find a thread-safety issue
> with that approach?
>

You would still have the performance hit, but AFAIR the thread-safety issue
only exists if you have multiple writers, which probably does not match the
static configuration data use-case? Nevertheless, you are right, one can
perfectly imagine a use-case where it would be a problem.

R.

> S
>
>
> R.
>
>
>>
>> We are *not* saying that the v2 flow status port implementation is bad,
>> wrong or incorrect, We're simply saying that it doesn’t deal with some
>> valid use cases. The question is, what does the community think, and what
>> should be done about it?
>>
>> Cheers
>> Stephen
>>
>
>

Limitations with v2 port implementation

On Wed, 8 Apr 2015, S Roderick wrote:

> We have ported a large Orocos system from v1 to v2, and identified some limitations in the v2 port implementation that we wanted to discuss with the community.
>
> v1 ports essentially had one connection object, and thus one value. When you connected/read the port, you got the last value that was written. There was no concept of “flow” (i.e. when a connection object was updated).
>
> v2 ports have one “object" per input/output connection, and maintain potentially different values and flow status per connection (yes, I’m simplifying here). So one output port connected to N input ports will have N connections, each with potentially different values and flow status.
>
> We’ve run into two issues with v2 ports:
>
> 1) performance when writing to output ports is much slower in v2 than v1, as essentially the update occurs to multiple connection objects in v2 (in v1 it occurred to one connection object). One of our components has a 450% slow down when writing to its eight (8) output ports.
>
> 2) flow status does not cover the use case where you want a single connection object, and don’t care when a connection is made nor when a value is written (i.e. you don’t care about “flow”). One of our examples here is static configuration data (say the name, model or serial number, of a device, or a robot’s number of DOF). When the source component is configured or started, it writes the appropriate data to the port. If a connection is made in the future (say by a GUI, or by a reporting component that has dynamically created ports) then v2 ports will not present the value that was previously written (I believe as there has been no “flow” of data since the connection was made). In this use case, we believe that the v1 single-connection-object semantics made more sense as connected peer components are only interested in the value, and not when it was written nor whether it has been updated (i.e. they don’t care about flow).
>
> We are *not* saying that the v2 flow status port implementation is bad, wrong or incorrect, We're simply saying that it doesn’t deal with some valid use cases. The question is, what does the community think, and what should be done about it?

My position on this is that communication policies should be fully
decoupled from the container component policies. In other words:
- choose whatever communication middleware and p2p architecture and
"flow" policy that your application need;
- let the container component be triggered by any input on any of its ports;
- introduce a "scheduler" that decides how to react to that trigger;
- let the trigger trigger the computational component(s) inside the
container that are involved in the communication.
This is neither v1 nor v2...

> Cheers
> Stephen

Herman

Limitations with v2 port implementation

Op 9-apr.-2015 11:57 schreef "Janosch Machowinski" <
Janosch [dot] Machowinski [..] ...>:
>
> Hey,
> there is another issue with the current port implementation,
> it might be related. The current implementation always searches
> all known connections in a linear way and returns the first one
> that has a sample.

That is not entirely correct. The search only happens when the current
connection has no more data. This is indeed an extra penalty since each
read on an empty port causes a search on all connections.

This is bad for runtime issues, and (even if this
> is more theoretical) bad in terms of starvation. What I mean is,
> if the sample take a lot of time to be processed between read
> calls, so that new samples arrive in between on the first connections,
> the last connections will never be read.

I think it already goes circular over the connections list ?

> Perhaps adding some sort of clock hand algorithm helps here.
> Greetings
> Janosch

Peter

Limitations with v2 port implementation

2015-04-09 8:34 GMT-03:00 Peter Soetens <peter [..] ...>:
> Op 9-apr.-2015 11:57 schreef "Janosch Machowinski"
> <Janosch [dot] Machowinski [..] ...>:
>>
>> Hey,
>> there is another issue with the current port implementation,
>> it might be related. The current implementation always searches
>> all known connections in a linear way and returns the first one
>> that has a sample.
>
> That is not entirely correct. The search only happens when the current
> connection has no more data. This is indeed an extra penalty since each
> read on an empty port causes a search on all connections.

There are indeed two problems with the current behaviour (I'm not sure
whether it includes the one Janosch is experiencing, though):
1. if the components do not manage to empty the "current" channel
then the other channels will never be read.
2. if one has multiple active connections and means to empty all of
them, then there is a pretty high penalty of N^2/2 reads, since each
time you empty the channel, you go through the channel list to find
the next non-empty channel. That could very well be the actual non
linear complexity I hinted about in previous emails.

For 1., a strong never-worded assumption in RTT, the first thing
components should do is empty their connections. If you can't empty
your connection, you'll have to change the policies to make buffers
smaller (since, in any case, you *will* have trouble, changing how RTT
behaves in this case will just hide the problems until it hits you in
another way).
For 2, assuming that the N^2 iteration complexity is indeed the source
of the problem, one solution would be to:
- have a per-channel 'active' flag. Any signalling channel returning
NoData or OldData will be marked as empty. Non-signalling channels are
always left active. The flags are stored in the channel manager to
avoid having to iterate through the channel list (which is costly)
- use the signals in the channel manager to move channels back to
active when a signal is received. It would avoid the quadratic cost
when using non-polling or polling but signalling connections .
However, I would personally NOT accept any patch in this respect until
someone actually did some profiling to find out whether it actually is
the problem. No changes "for performance" that are not backed by
actual profiling data.
- make all non-polling connections signalling since there's virtually
no cost in doing so (but don't propagate the signal to the task
context if it is not an event port)

Sylvain