lib: notification iterator: transfer a batch of notifications
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 22 Jun 2018 20:54:27 +0000 (16:54 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 2 May 2019 04:05:45 +0000 (00:05 -0400)
commitd4393e0875e7b08f6ee97d617cc5f2c9286742a4
tree299de9a2f5e24b38ea626f1fd611b79f1e6219e1
parent26e21a82c47a15d1080dc142cb20c0b0b0b5a929
lib: notification iterator: transfer a batch of notifications

This patch makes each notification iterator's "next" operation return a
batch of notifications intead of a single one. This has a positive
effect on performance as we're decreasing the number of executed
instructions because there are fewer function calls per notification.

The batch size is arbitrarily set to 15 here as a value between 10 and
50 experimentally showed to be beneficial, and there's usually more than
one active stream on a typical graph configuration. As the batch size
increases, the performance eventually degrades, as I suspect that
(pooled) notification objects are constantly getting into and out of CPU
cache. The goal of hiding the batch size in the library's implementation
is to eventually determine a value at run time depending on the
situation, and even change it when needed between consuming sinks.

Each notification iterator contains a fixed-sized array of notification
pointers. This array is allocated when the iterator is created and freed
when it is destroyed. For convenience, I'm adding this typedef:

    typedef struct bt_notification **bt_notification_array;

Consumer side
=============
The consuming side API is now:

    enum bt_notification_iterator_status
    bt_private_connection_notification_iterator_next(
        struct bt_notification_iterator *iterator,
        bt_notification_array *notifs, uint64_t *count);

    enum bt_notification_iterator_status
    bt_output_port_notification_iterator_next(
        struct bt_notification_iterator *iterator,
        bt_notification_array *notifs, uint64_t *count);

In English: the function sets `notifs` to the address of a notification
array containing `*count` notifications when the returned status is
`BT_NOTIFICATION_ITERATOR_STATUS_OK`. In this case, the caller is
responsible for putting each notification in the array (the array's
content is owned by the caller, but not the array itself), as the
functions above do not put what's already in the iterator's array before
filling it. If the status is not `BT_NOTIFICATION_ITERATOR_STATUS_OK`,
then the function does not set `*notifs` and `*count`.

Because the `utils.flt.muxer` component class kept each upstream
notification iterator's current notification, it now keeps a queue of
notifications, and the upstream iterator is now considered invalid if
its notification queue is empty.

If less than `*count` notifications are required, the caller can either:

* Discard (put) unneeded notifications: they are lost forever.

* Keep a queue (or other data structure) of notifications by keeping the
  references. The caller must NOT keep the array itself in this case,
  but each contained notification object, copying the pointer values to
  its territory.

Producer side
=============
The "next" method signature is now:

    enum bt_notification_iterator_status next_method(
        struct bt_private_connection_private_notification_iterator *notif_iter,
        bt_notification_array notifs, uint64_t capacity,
        uint64_t *count);

The callback must either:

* Fill `notifs` with up to `capacity` notifications (notification's
  ownership is transfered to the array), set `*count` to how many
  notifications were transfered (at least one), and return
  `BT_NOTIFICATION_ITERATOR_STATUS_OK`.

  `capacity` is always greater than zero.

* Return something else than `BT_NOTIFICATION_ITERATOR_STATUS_OK`,
  not touching `notifs` and `count`.

IMPORTANT: The callback must NOT transfer one or more notifications to
`notifs` and return something else than
`BT_NOTIFICATION_ITERATOR_STATUS_OK`.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
27 files changed:
include/babeltrace/graph/component-class-sink-colander-internal.h
include/babeltrace/graph/component-class.h
include/babeltrace/graph/notification-iterator-internal.h
include/babeltrace/graph/notification.h
include/babeltrace/graph/output-port-notification-iterator.h
include/babeltrace/graph/private-connection-notification-iterator.h
lib/graph/component-class-sink-colander.c
lib/graph/iterator.c
plugins/Makefile.am
plugins/ctf/common/notif-iter/notif-iter.c
plugins/ctf/fs-src/data-stream-file.c
plugins/ctf/fs-src/data-stream-file.h
plugins/ctf/fs-src/fs.c
plugins/ctf/fs-src/fs.h
plugins/text/dmesg/dmesg.c
plugins/text/dmesg/dmesg.h
plugins/text/pretty/pretty.c
plugins/utils/Makefile.am
plugins/utils/counter/counter.c
plugins/utils/counter/counter.h
plugins/utils/dummy/dummy.c
plugins/utils/muxer/muxer.c
plugins/utils/muxer/muxer.h
tests/lib/test-plugin-plugins/sfs.c
tests/lib/test_bt_notification_iterator.c
tests/lib/test_graph_topo.c
tests/plugins/test-utils-muxer.c
This page took 0.027422 seconds and 4 git commands to generate.