Creating a flow controller overrides the default?

4 posts / 0 new
Last post
Offline
Last seen: 2 years 4 months ago
Joined: 02/08/2021
Posts: 21
Creating a flow controller overrides the default?

I added a custom flow controller in our DDS wrapper; the thing we expose to our users.

So on each domain participant abstraction object (1 x app) I attach and initialize a flow controller like the fixed rate one (rti::pub::FlowController::FIXED_RATE_NAME), but at 40Hz. This is ready to use but not a default.

We abstract the writer modes as an enum. So then internally when the user creates a writer qos through the wrapper, we set either:

writer_qos.policy(rti::core::policy::PublishMode::Synchronous());

Or:

writer_qos.policy(rti::core::policy::PublishMode::Asynchronous(getFlowControllerName(our_enum)));

Where the "getFlowControllerName" function, just returns the name of the flow controller, so DEFAULT_NAME, ON_DEMAND_NAME, FIXED_RATE_NAME or our custom FlowController's name. As below:

switch (cfg)
{
    case qos::writer_mode::sync:
        return {};
    case qos::writer_mode::async_fifo:
        return ::rti::pub::FlowController::DEFAULT_NAME;
    case qos::writer_mode::async_on_demand:
        return ::rti::pub::FlowController::ON_DEMAND_NAME;
    case qos::writer_mode::async_fixed_rate_1hz:
        return ::rti::pub::FlowController::FIXED_RATE_NAME;
    case qos::writer_mode::async_fixed_rate_40hz:
        return flowcontroller_40hz_name;
    default:
        throw local_error("Unknown qos::writer_mode");
        break;
}

We introduced the change keeping all the current configurations the same, all tests passing, but after merge we have been reported slowdowns on a team using replay and a bisect shows this change is the culprit.

If I remove our own (still unused) 40Hz flow controller the slowdown goes away.

So here's the question. Does creating a flow controller, even when not using it, has an effect on the global state? Is it made the default flow controller?


Howard's picture
Offline
Last seen: 15 hours 55 min ago
Joined: 11/29/2012
Posts: 565

No, just creating a flow controller in the DomainParticipant doesn't cause it to be used.  You have to create an Asynchronous DataWriter configured to use the flow controller by name.

Flow Controllers are ONLY used when there are asynchronous DataWriters.  There is a DEFAULT flow controller used by an asynchronous DataWriter if you create it without assigning it a flow controller.  But what is the DEFAULT flow controller cannot be changed.

If you need help to figure out what's happening in your system, you should contact RTI's support team.

Offline
Last seen: 2 years 4 months ago
Joined: 02/08/2021
Posts: 21

Well, it's weird then, because removing it reproducibly shows different behavior on its application using replay features.

Without it, each iteration (of whatever they do) runs from 10-20ms with an occassional one taking 500ms now and then. With it enabled (but unused), after 100 iterations every iteration takes around 800ms.

I only see messages of Domain participant creation (the moment the FlowController is created) at simulation startup. Our DomainParticipant wrapper objects wrap the DomainParticipant implementation object (owning the flow controller) with shared pointers, and the object that the users create reuses Domain participants (by domain) from a global register. There are not many lying DomainParticipants (and flow controllers) around, just one per DomainParticipant. I guess a FlowController name only needs to be unique for each DomainParticipant, not globally.

Anyways, both RTI libs and the Application are black boxes to me and I'm satisfied with the workaround and with knowing that the FlowController is not made the new default, as this was added because it wasn't obvious how to map it into our abstraction. Now it's on the GIT history.


Howard's picture
Offline
Last seen: 15 hours 55 min ago
Joined: 11/29/2012
Posts: 565

Sorry, what is the workaround?

The problem of going from 10/20 ms to 800 ms per iteration seems pretty severe and strange.  I would try to use a profiler to see where that time is being spend...or how the time is spent different between the two cases.