Announcing iceoryx2 v0.3.0

Christian Eltzschig - 18/04/2024

iceoryx2

Today, I am happy to announce iceoryx2 v0.3.0. The release comes with cool new features, improved documentation and additional examples.

So here we go.

Features & Improvements

Communication Between Docker Containers

With iceoryx2, you can establish zero-copy communication between multiple docker containers. Since iceoryx2 is just using shared memory and some files stored in /tmp/iceoryx2 for communication, all you have to do is to share /tmp/iceoryx2 and /dev/shm with all your docker containers, and everything works. We created a docker example that explains all the little details.

Note: All paths and naming schemes can be configured via a config file. For more details and documentation, take a look at the iceoryx2 default configuration

Services Without Lifetime Parameters

In v0.2, every endpoint and payload sample in iceoryx2 had generic lifetime parameters. The idea was that a service is, from a high-level point of view, a factory of endpoints like publishers or subscribers. Those endpoints were again factories for samples. For instance, a subscriber "produces" a sample when the call my_subscriber::receive() returns the received sample. Under the hood, the service created system resources that had to live as long as any endpoints or samples were active. Therefore, the service must live as long as an endpoint and an endpoint at least as long as a sample.

But you run into trouble when you would like to store samples from different endpoints, with different lifetimes, in a Vec to cache them for later. But thanks to Arc, which allowed us to share the ownership of those resources, the problem is gone, and the API is now much easier to use.

Sending Complex Data

Usually, you want to send more complex data than just arrays of integers via shared memory. This is why iceoryx2-bb-containers becomes public API with this iceoryx2 release. It comes with compile-time fixed-size versions of Queue, Vec, and ByteString that can be used as building blocks for transmission types.

use iceoryx2_bb_container::{
    byte_string::FixedSizeByteString, vec::FixedSizeVec,
};

#[derive(Debug, Default)]
#[repr(C)]
pub struct ComplexDataType {
    text: FixedSizeByteString<8>,
    vec_of_data: FixedSizeVec<u64, 4>,
}

If you would like to see a complete working example, take a look at the complex data types example

Note: I know defining the capacity at compile-time is not yet perfect. However, we are working on runtime dynamic data types based on relocatable containers that will be available with an upcoming release.

Then, you can define your transmission types without any compile-time restrictions.

use iceoryx2_bb_container::vec::RelocatableVec;

#[derive(Debug, Default)]
#[repr(C)]
pub struct ComplexDataType {
    some_data: RelocatableVec<u64>,
    other_data: RelocatableVec<f32>,
}

Improved Event Communication

The event messaging pattern is iceoryx2's basic building block for async operations and push notifications. The new release is based on the ported C++ iceoryx1 bitset, which solves the problem of a limited queue buffer on the listener side.

When a Notifier sends notifications with their EventIds in a busy loop, the buffer is filled quickly, and other Notifiers cannot send their notifications to the Listener. A bitset where the Notifier flips a bit corresponding to the EventId solves the issue.

Furthermore, we refined the API so that you can choose to take either one EventId after another in a loop:

for event_id in listener.blocking_wait_one()? {
    println!("event was triggered with id: {:?}", event_id);
}

or to acquire all received EventIds at once

listener.blocking_wait_all(|id| {
    println!("event was triggered with id: {:?}", id);
})?;

Bug Fixes

A big thanks to our first users, who started playing around with iceoryx2 and helped us refine the API and iron out the edges.

We fixed a ton of bugs!

Most bugs were connected to the decentralized nature of iceoryx2, and we encountered some races when endpoints connected and disconnected at a high frequency. However, many additional concurrent stress tests now give us the confidence that they stay fixed.

The communication mechanism did not raise bug reports, mainly because they were proven-in-use for years in iceoryx1 and were just ported to iceoryx2.

Performance Improvements

We took some time to improve the performance of iceoryx2 even further and realized that we hit a limit where the performance becomes very architecture/OS dependent. Look at the iceoryx2 readme where we provide an overview of our results.

What Comes Next

Take a look at our Roadmap.

In Q2 we want to focus:

  • on our first language binding to C
  • introduce advanced monitoring so that manual cleanups are no longer required when an application has crashed
  • on sending serializable structs via shared memory so that any kind of type - without restriction - can be sent