Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORBA efficiency patches #123

Merged
merged 27 commits into from
May 8, 2019

Conversation

meyerj
Copy link
Member

@meyerj meyerj commented Dec 15, 2015

This PR is the result of some work we did last year to optimize the CORBA inspection and transport, especially for systems where the network is affected by transport delay and packet loss. Actually I already wanted to open a PR to merge into master since a long time, but now #122 reminded me that I actually never did that. This branch has already been used in some bigger deployments and I would consider it as ready to be merged.

The existence of this patch has already been mentioned in a side note during the update dataflow semantics discussion on the mailing list: http://www.orocos.org/forum/rtt/rtt-dev/updated-dataflow-semantics-rtt#comment-36662

Major updates

Most changes in the CORBA transport affect the way a TaskContextProxy synchronizes its objects (ports, operations, properties, services etc.) with the remote server. The number of CORBA calls going over the network has been greatly reduced. In fact, the proxy requests one big TaskContextDescription object in a single call now instead of enumerating all task objects subsequently.

Furthermore write() and (optional, reverted in #151) remoteSignal() calls for port connections via a CORBA transport have been converted to oneway calls, which means that the writer (the CORBA dispatcher of the writing TaskContext) is not blocking anymore (see also #122). The signalling can be disabled completely if appropriate (see section Optional patches).

Caveats

The IDL is not compatible to previous RTT releases, so both sides of a connection have to updated synchronously.

Optional patches

The following patches are only enabled on demand (at compile time of RTT) as they can change the behavior of the application, beyond pure optimization. They can be enabled by setting the corresponding Cmake variables to ON. Default state is OFF.

PLUGINS_CORBA_PORTS_DISABLE_SIGNAL

When a port is connected to a remote port with the pull flag of the ConnPolicy set to true, the writing side normally signals the reader to notify him about new data. If PLUGINS_CORBA_PORTS_DISABLE_SIGNAL is enabled, the remoteSignal() call is skipped. This is only for saving bandwidth if data is written periodically anyway. The subsequent read() call to fetch the data blocks the reader, so pulling connections are not well suited for robot to GUI connections anyway unless the GUI reads only on demand or there is a separate thread that periodically reads all input ports.

Note that adding input ports which are only connected through a remote connection to a component as an event port will not trigger the component if remote signalling is disabled.

PLUGINS_CORBA_NO_CHECK_OPERATIONS

Normally the remote side checks the validity of the signature whenever it produces a handle for a remote operation call (or send), so for every OperationCaller connection in C++ or every call to a remote operation in scripting. The PLUGINS_CORBA_NO_CHECK_OPERATIONS cmake flag will disable this check, which means that wrong signatures cannot be detected while the OperationCaller is connected (usually in the configureHook or startHook) or when a script is loaded. Calling or sending an operation with a wrong signature will results in an exception during runtime instead.
Omitting the checkOperation() calls greatly reduces the setup time for the GUI (approx. by factor 2).

PLUGINS_CORBA_SEND_ONEWAY_OPERATION

This cmake switch enables oneway sending of operations which have a collect arity of zero (return void and have no reference arguments). The advantage is that the send() call does not block until the CSendHandle is returned. On the other side, without the handle it is impossible to check whether the operation has finished or if an exception occured. Exceptions or cases where an operation has been send with the wrong signature (if PLUGINS_CORBA_NO_CHECK_OPERATIONS is also active) at least prints an error log message at the server side.
Calling operations is not affected by this patch and always blocks until the operation finishes and the result is returned by the remote side.

PLUGINS_CORBA_PORTS_WRITE_ONEWAY

Although port writes could be communicated through oneway method calls on the CORBA layer for efficiency, the original patch (08b77c4) which applied this change unconditionally broke the guaranty that input ports read the samples in the same order as they have been written to the output port. Due to multi-threading in the CORBA implementation (depending on its implementation and its configuration) this guaranty did not hold anymore, which caused issues (discussion starting in #123 (comment)) and occasional unit test failures.

Therefore this part has been reverted in #151 and replaced by an optional build-time configuration variable PLUGINS_CORBA_PORTS_WRITE_ONEWAY.

@meyerj meyerj self-assigned this Dec 15, 2015
@meyerj meyerj added this to the 2.9 milestone Dec 15, 2015
…formation in one remote call per TaskContext

Signed-off-by: Johannes Meyer <[email protected]>
…S to enable or disable oneway operations

If PLUGINS_CORBA_SEND_ONEWAY_OPERATIONS is set to ON, operations that have a collect arity of zero
(void return value and no reference arguments) are sent as oneway calls. The fake SendHandle returned to
the caller will always evaluate to SendSuccess, as if the operation would have been completed successfully.

Note that exceptions in the operation implementation are not forwarded to the caller and print a log message
at the server's side only.

Signed-off-by: Johannes Meyer <[email protected]>
…to disable remote signalling

If PLUGINS_CORBA_PORTS_DISABLE_SIGNAL is set to ON, writing into ports that are connected to a remote
port via the CORBA transport will not signal the remote side or trigger the owning TaskContext. The
remote side has to poll the port periodically.

Signalling is only active if pull is set to true in the ConnPolicy. Otherwise every write() is pushed
to the remote side and PLUGINS_CORBA_PORTS_DISABLE_SIGNAL has no effect.

Signed-off-by: Johannes Meyer <[email protected]>
…o disable operation signature checking

If PLUGINS_CORBA_NO_CHECK_OPERATIONS is set to ON, producing call and send handles for remote operations
will not check the argument types. Instead, calling or sending operations with an incompatible signature
will trigger an exception at runtime.

Signed-off-by: Johannes Meyer <[email protected]>
@meyerj meyerj force-pushed the corba-efficiency-patches branch from 23331ec to b3e9db2 Compare December 15, 2015 19:05
@meyerj
Copy link
Member Author

meyerj commented Dec 15, 2015

rebased on master

@meyerj meyerj force-pushed the corba-efficiency-patches branch from 0c200be to 2f34384 Compare December 15, 2015 19:31
planthaber added a commit to planthaber/tools-orocosrb that referenced this pull request Dec 16, 2015
@@ -125,17 +137,18 @@ module RTT
*/
interface COperationInterface
{
typedef sequence<string> COperationList;
typedef sequence<string> COperationList;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to adapt rock's ruby bindings to this PR for my test in #122

Had to switch to COperationDescriptions from COperationList and found that the COperationList typedef here is still defined but not used anymore.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, COperationList should be removed.

@doudou
Copy link
Contributor

doudou commented Dec 18, 2015

Since it's incompatible for e.g. the Rock bindings, would it be possible to have a way to test for the change at the preprocessor level ? That would allow to be compatible with both the new and old interface.

@meyerj
Copy link
Member Author

meyerj commented Dec 18, 2015

I started to create toolchain-2.9 branches which have the corba-efficiency-patches (#123), the updated-dataflow-semantics (#114) and also the new RTT_VERSION_GTE preprocessor macro (#115) already integrated. With this branch you could compile tools-orocosrb conditionally:

#if RTT_VERSION_GTE(2,9,0)
// ...
#endif

There might be more small API changes that require adaptations in the Ruby bindings for rtt 2.9.
Or do you had something else in mind with "a way to test for the change at the preprocessor level"?

I am currently working on the Toolchain 2.9 release which has most of the open PRs with API breaking changes merged in. Peter already wrote down some release notes (orocos-toolchain/orocos_toolchain#12). I wanted to ask the orocos-dev mailing list for comments during the next days, especially what branch/tag of typelib and orogen should be considered as stable. For now I am using the rock-15.05 tag present in most of the repos.

@doudou
Copy link
Contributor

doudou commented Dec 21, 2015

The problem with orogen is that you still have a pretty heavily forked version of it. The major difference it will make for you between rock-15.05 and master is that master is "ready" for clang (not meaning that it works, but at least most of the ground work is there)

@meyerj
Copy link
Member Author

meyerj commented Dec 21, 2015

From #122 (comment):

It should be noted that with the merged branches corba-efficiency-patches (#123) and updated-dataflow-semantics-rebased (#114) in toolchain-2.9 writes are only send as one-way calls if the connection is not mandatory (see new flag mandatory in ConnPolicy.hpp). The differentiation happens in RemoteChannelElement.hpp:351.

After I wrote this I noticed that because all writes through CORBA are buffered and forwarded by the CorbaDispatcher thread, the WriteStatus return value as returned by the RemoteChannelElement is invisible to the caller anyway. In that case we could also stick to one-way writes in all cases. I updated the merge commit in 3643898.

On the other hand it must be clearly documented that failures during transport (e.g. packet loss) or at the remote side (e.g. full input buffer) are not reflected in the WriteStatus returned to the original writer.

@meyerj
Copy link
Member Author

meyerj commented Feb 12, 2016

Just found another caveat when writes are oneway: There is no guaranty on the order of arrival of write operations anymore:

Task A: 1.588 [ Debug  ][Thread] RemoteChannelElement(0x111f8d0): write(6.33) -> CORBA
Task A: 1.588 [ Debug  ][Thread] RemoteChannelElement(0x111f8d0): write(6.33) finished.
Task A: 1.588 [ Debug  ][Thread] RemoteChannelElement(0x111f8d0): write(3.33) -> CORBA
Task A: 1.588 [ Debug  ][Thread] RemoteChannelElement(0x111f8d0): write(3.33) finished.
Task B: 380.228 [ Debug  ][SendHandleC] RemoteChannelElement(0x7fb89c1b19a0): CORBA -> write(3.33)
Task B: 380.228 [ Debug  ][SendHandleC] RemoteChannelElement(0x7fb89c1b19a0): CORBA -> write(6.33)
Task B: 380.228 [ Debug  ][SendHandleC] Received 3.33
Task B: 380.228 [ Debug  ][SendHandleC] Received 6.33

@doudou
Copy link
Contributor

doudou commented Feb 12, 2016

@meyerj
Copy link
Member Author

meyerj commented Feb 12, 2016

Since it's incompatible for e.g. the Rock bindings, would it be possible to have a way to test for the change at the preprocessor level ? That would allow to be compatible with both the new and old interface.

@doudou What exactly would be incompatible? Can you point me to some code? At the Port or TaskContext(Proxy) API level you should not see a difference. Of course the CORBA IDL and the RemoteChannelElement API changed.

Anyway, you can check the version of RTT with a macro introduced in #115, so that if this PR would be applied to version 2.9 only, you can write code like

#include <rtt/rtt-config.h>

#ifdef RTT_VERSION_GTE
#if RTT_VERSION_GTE(2,9,0)
    // with corba-efficiency-patches
#endif
#else
    // without corba-efficiency-patches
#endif

There are no preprocessor macros that allow conditional compilation directly based on the availability of certain RTT features.

Luca Magnabosco and others added 9 commits August 23, 2017 10:21
corba: avoid some corba calls improving getArgumentList()
… the remote side has no CORBA transport for that type

Like bfd3184 for buildChannelOutput(). The same problem
can occur in buildChannelInput().

type_info->getProtocol(ORO_CORBA_PROTOCOL_ID) always returns a valid CorbaTypeTransporter,
which might be of type CorbaFallBackProtocol. So the check a few lines above is not
effective and we can only know that there is no specific CORBA transport for that type
after createChannelElement_i() returned a null pointer, which without the added check would
have caused a segfault.

Signed-off-by: Johannes Meyer <[email protected]>
…rFactory::getArgumentType()

This commit fixes a regression from 3b1e482.

COperation mdescription contains fully-qualified argument types as returned
by OperationInterfacePart::getArgumentList() and DataSourceTypeInfo<T>::getType(),
while COperationInterface::getArgumentType() would return the unqualified type
name as DataSourceTypeInfo<T>::getType().

Signed-off-by: Johannes Meyer <[email protected]>
…write call

This is especially required if the other end of the connection disappeared, in order to properly cleanup
and to not spam the log with transient CORBA errors. If required, it is up to the user application to
reestablish the connection automatically in case the connection breaks.

Instead, we check the return value of updateAny/updateFromAny and return a WriteFailure in case conversion fails.
This is most likely a temporary error and not due to a broken CORBA connection.

Signed-off-by: Johannes Meyer <[email protected]>
This reverts commit 3643898, which removed the writeOneway() method
from the CChannelElement interface. With oneway writes we cannot guarantee that samples are never
reordered even on a single connection due to potential multi-threading within the CORBA implementation.

This patch introduces a new cmake flag PLUGINS_CORBA_PORTS_WRITE_ONEWAY, which enables oneway writes
and has to be set explicitly when RTT is configured. Otherwise the old behavior of using standard
two-way calls is restored. Note that it is not possible to configure this during run-time or even
per-connection, which would require an extension in the ConnPolicy struct.

The CORBA transport option flags have been added to the generated rtt-corba-config.h header file.
This allows to use them in header files required to generate transport plugins in dependent packages
(see also 2f34384) and removes the need to pass them as individual constructor arguments
to new RemoteChannelElement instances. Instead, every RemoteChannel instance has a full copy of
the ConnPolicy struct now, which allows to adapt its run-time behavior in a more flexible way without
the need to change the signature of the constructor or factory methods in the future.

Signed-off-by: Johannes Meyer <[email protected]>
Tested with tao 2.3.1:
- fixed Service.idl, line 35: Error: anonymous types are deprecated by OMG spec
- fixed ServiceRequester.idl, line 31: Error: anonymous types are deprecated by OMG spec
- fixed different exception specifier in implementation of
  CDataFlowInterface_i::createSharedConnection()
- some whitespace indentation updates
- removed server inline skeleton files from the list of files to be generated and installed
  in the ORO_ADD_CORBA_SERVERS() cmake macro for TAO. tao_idl does not generate these files
  and hence cmake complains when it tries to install them.

Signed-off-by: Johannes Meyer <[email protected]>
corba: revert oneway writes and fixed connection cleanup and TAO builds
@meyerj
Copy link
Member Author

meyerj commented Oct 17, 2017

Re-merged into toolchain-2.9 in 171ed58.

@meyerj meyerj force-pushed the corba-efficiency-patches branch from 313d376 to 44e5ce1 Compare October 22, 2017 00:22
@meyerj meyerj force-pushed the corba-efficiency-patches branch from 44e5ce1 to 83b9770 Compare October 22, 2017 00:44
meyerj added a commit to meyerj/rtt that referenced this pull request Oct 27, 2017
…-pick

CORBA efficiency patches

Added two patches:
ea9de93 transports::corba fix crash retrieving property name through corba
0175877 corba: improve log output in case of unsufficient type info during the synchronization of component interfaces
@meyerj
Copy link
Member Author

meyerj commented Apr 11, 2019

@planthaber @doudou Do you agree with merging this old patch along with a version bump to at least 2.9 into master and to follow-up on the remaining issues about partitioning the remote connections in #227 and #248?

This pull request is mainly about the more efficient communication of the TaskContext description and the oneway writes have been reverted due to reordering issues (#151) (unless RTT is compiled with PLUGINS_CORBA_PORTS_WRITE_ONEWAY).

@planthaber
Copy link
Contributor

I don't see an issue with the merge

2 similar comments
@planthaber
Copy link
Contributor

I don't see an issue with the merge

@planthaber
Copy link
Contributor

I don't see an issue with the merge

@doudou
Copy link
Contributor

doudou commented Apr 15, 2019

Sounds good to me too.

@meyerj meyerj merged commit f0bd90c into orocos-toolchain:master May 8, 2019
@meyerj meyerj deleted the corba-efficiency-patches branch May 8, 2019 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants