OnixS ICE iMpact Multicast Price Feed Handler C++ library  8.17.0
API documentation
Setting Up Feed Engine

The Feed Engine concept encapsulates network-related aspects to let the Handler focus on market data processing. It also provides advanced facilities on utilizing system resources used by the Handler to achieve best performance and latency characteristics.

Previously, there were no shared services between the Handler instances. Thus, system resources were allocated exactly for and by a particular instance. That caused certain inefficiency regarding resources utilization. For example, each Handler instance used from one to two threads to manage incoming market data processing. As a result, the number of threads used by multiple Handler instances was multiplied by the number of those instances and significantly exceeded the effective amount of resources required to solve the market data processing task.

The concept of the Feed Engine was involved to make things more efficient. The Feed Engine machinery is used by the Handler to receive and process market data starting from the recent major release. Multiple Handler instances can share a single instance of the Feed Engine.

Using Feed Engine

The OnixS::ICE::iMpact::MarketData::FeedEngine class represents the Feed Engine concept. The Feed Engine events are reported through an instance of the OnixS::ICE::iMpact::MarketData::FeedEngineListener class, associated with the Feed Engine instance at the constructing stage.

The following code sample depicts primary aspects of using the Feed Engine with two Handler instances:

// STEP 1: is to set configuration parameters.
FeedEngineSettings feedEngineSettings;
feedEngineSettings.threadsCount = NUMBER_OF_WORKING_THREADS;
// STEP 2: is to construct shared feed engine.
FeedEngine feedEngine(feedEngineSettings);
// STEP 3: is to bind feed engine to Handler instances.
handler.bindFeedEngine(feedEngine);
Note
Market data processing is done inside of working threads managed by the Feed Engine. A size of the internal thread pool is defined by the OnixS::ICE::iMpact::MarketData::FeedEngineSettings::threadCount parameter.

Feed Engine Events

All Feed engine events are encapsulated into the OnixS::ICE::iMpact::MarketData::FeedEngineListener class interface. OnixS::ICE::iMpact::MarketData::FeedEngine class accepts an instance of listener upon construction.

The following table uncovers Feed Engine events:

Event Description
OnixS::ICE::iMpact::MarketData::FeedEngineListener::onFeedEngineThreadBegin

Invoked by the Feed Engine working thread before entering a master processing loop.

Event callback is invoked in the context of working thread allowing the subscriber to perform thread-specific turning like setting affinity or priority for the thread.

OnixS::ICE::iMpact::MarketData::FeedEngineListener::onFeedEngineThreadEnd

Invoked by the Feed Engine when working thread is about to end.

The given event callback is invoked in the context of the working thread allowing the subscriber to perform thread-specific cleanup like deleting data stored in thread local storage.

OnixS::ICE::iMpact::MarketData::FeedEngineListener::onFeedEngineThreadIdle

Invoked by the Feed Engine when the working thread is idle.

At an active phase, the Feed Engine working thread is running a market data processing loop. The working thread may wait for incoming market data using an appropriate I/O operation.

A working thread raises the given event if there was no incoming data detected for a certain time interval (defined by the OnixS::ICE::iMpact::MarketData::FeedEngineSettings::dataWaitTime parameter). The OnixS::ICE::iMpact::MarketData::FeedEngineThreadIdleReasons::DataWaitTimeout is passed as a reason of the idle state.

It may happen that a thread misses entering waiting for incoming data because other threads have already been doing that for all active feeds, and there are no other tasks like the processing already received market data. In such case, the working threads spin for a certain time (defined by the OnixS::ICE::iMpact::MarketData::FeedEngineSettings::spinBeforeIdleTime parameter value) while waiting for any pending tasks to be executed. If no pending tasks were found, the working thread enters an idle state with the OnixS::ICE::iMpact::MarketData::FeedEngineThreadIdleReasons::Redundant reason.

The given event callback also exposes a parameter-variable which value represents the time interval the working thread is suggested to spend sleeping to reduce races between working threads for executing pending tasks (data reception, data processing, etc.) and thus to reduce a load onto CPU. The parameter value can be modified inside the callback body.

Note
It's not recommended to change the sleep time interval when the working thread entered idle state after waiting for incoming data to avoid overflow of a buffer used for incoming data.
Warning
There's no predictability in firing the given event by the Feed Engine. Each working thread may wait for incoming data or receive incoming data or process data previously received by that or any other threads. Availability of active tasks, which are executed by the working threads, depends on many factors including some bound Handler instances, system capacity, and a number of allocated working threads, clock resolution, and other factors.