<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD Journal Publishing DTD v2.3 20070202//EN" "journalpublishing.dtd">
<article xml:lang="EN" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" article-type="review-article">
<front>
<journal-meta>
<journal-id journal-id-type="publisher-id">Front. Big Data</journal-id>
<journal-title>Frontiers in Big Data</journal-title>
<abbrev-journal-title abbrev-type="pubmed">Front. Big Data</abbrev-journal-title>
<issn pub-type="epub">2624-909X</issn>
<publisher>
<publisher-name>Frontiers Media S.A.</publisher-name>
</publisher>
</journal-meta>
<article-meta>
<article-id pub-id-type="doi">10.3389/fdata.2023.1227156</article-id>
<article-categories>
<subj-group subj-group-type="heading">
<subject>Big Data</subject>
<subj-group>
<subject>Conceptual Analysis</subject>
</subj-group>
</subj-group>
</article-categories>
<title-group>
<article-title>A stream processing abstraction framework</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author" corresp="yes">
<name><surname>Bartolini</surname> <given-names>Ilaria</given-names></name>
<xref ref-type="corresp" rid="c001"><sup>&#x0002A;</sup></xref>
<uri xlink:href="http://loop.frontiersin.org/people/2320776/overview"/>
</contrib>
<contrib contrib-type="author">
<name><surname>Patella</surname> <given-names>Marco</given-names></name>
<uri xlink:href="http://loop.frontiersin.org/people/2436134/overview"/>
</contrib>
</contrib-group>
<aff><institution>Department of Computer Science and Engineering (DISI), Alma Mater Studiorum, University of Bologna</institution>, <addr-line>Bologna</addr-line>, <country>Italy</country></aff>
<author-notes>
<fn fn-type="edited-by"><p>Edited by: Vincenzo Moscato, University of Naples Federico II, Italy</p></fn>
<fn fn-type="edited-by"><p>Reviewed by: Alberto Ochoa Zezzatti, Universidad Aut&#x000F3;noma de Ciudad Ju&#x000E1;rez, Mexico; Daniela D&#x00027;Auria, Free University of Bozen-Bolzano, Italy</p></fn>
<corresp id="c001">&#x0002A;Correspondence: Ilaria Bartolini <email>ilaria.bartolini&#x00040;unibo.it</email></corresp>
</author-notes>
<pub-date pub-type="epub">
<day>25</day>
<month>10</month>
<year>2023</year>
</pub-date>
<pub-date pub-type="collection">
<year>2023</year>
</pub-date>
<volume>6</volume>
<elocation-id>1227156</elocation-id>
<history>
<date date-type="received">
<day>22</day>
<month>05</month>
<year>2023</year>
</date>
<date date-type="accepted">
<day>05</day>
<month>10</month>
<year>2023</year>
</date>
</history>
<permissions>
<copyright-statement>Copyright &#x000A9; 2023 Bartolini and Patella.</copyright-statement>
<copyright-year>2023</copyright-year>
<copyright-holder>Bartolini and Patella</copyright-holder>
<license xlink:href="http://creativecommons.org/licenses/by/4.0/"><p>This is an open-access article distributed under the terms of the Creative Commons Attribution License (CC BY). The use, distribution or reproduction in other forums is permitted, provided the original author(s) and the copyright owner(s) are credited and that the original publication in this journal is cited, in accordance with accepted academic practice. No use, distribution or reproduction is permitted which does not comply with these terms.</p></license></permissions>
<abstract>
<p>Real-time analysis of large multimedia streams is nowadays made efficient by the existence of several Big Data streaming platforms, like Apache Flink and Samza. However, the use of such platforms is difficult due to the fact that facilities they offer are often too raw to be effectively exploited by analysts. We describe the evolution of RAM3S, a software infrastructure for the integration of Big Data stream processing platforms, to SPAF, an abstraction framework able to provide programmers with a simple but powerful API to ease the development of stream processing applications. By using SPAF, the programmer can easily implement real-time complex analyses of massive streams on top of a distributed computing infrastructure, able to manage the volume and velocity of Big Data streams, thus effectively transforming data into value.</p></abstract>
<kwd-group>
<kwd>stream processing</kwd>
<kwd>real-time analysis</kwd>
<kwd>Big Data</kwd>
<kwd>multimedia data streams</kwd>
<kwd>software framework</kwd>
</kwd-group>
<counts>
<fig-count count="16"/>
<table-count count="2"/>
<equation-count count="0"/>
<ref-count count="19"/>
<page-count count="15"/>
<word-count count="8015"/>
</counts>
<custom-meta-wrap>
<custom-meta>
<meta-name>section-at-acceptance</meta-name>
<meta-value>Data Mining and Management</meta-value>
</custom-meta>
</custom-meta-wrap>
</article-meta>
</front>
<body>
<sec sec-type="intro" id="s1">
<title>1. Introduction</title>
<p>Starting from early 90&#x00027;s, multimedia (MM) data have been employed in a wide range of applications. The widespread accessibility of such data is made possible by the availability of inexpensive production (cameras, sensors, etc.) and storage technologies. Moreover, MM data frequently arrives in streams, or successions of the same sort of MM objects, which are received from a producer.</p>
<p>Significant value can be mined from MM streams, but there are also significant demands placed on computational capacity and analytical ability (Tang et al., <xref ref-type="bibr" rid="B15">2016</xref>). Real-time analysis, in particular, necessitates the processing of data streams at high throughput and low latency in order to take advantage of data freshness to act and make judgments rapidly.</p>
<p>A number of Big Data platforms exist (Zaharia et al., <xref ref-type="bibr" rid="B18">2010</xref>; Alexandrov et al., <xref ref-type="bibr" rid="B1">2014</xref>; Noghabi et al., <xref ref-type="bibr" rid="B9">2017</xref>) that provide services for the management and analysis of massive amounts of information, enabling evidence-based decision making across a wide range of human activities. However, the usage of such platforms is complicated for analysts, because their primary attention is on issues of fault-tolerance, synchronization, increased parallelism, and so forth, rather than offering programmers an intuitive interface.</p>
<p>In this paper, we show how RAM3S (Bartolini and Patella, <xref ref-type="bibr" rid="B2">2018</xref>, <xref ref-type="bibr" rid="B3">2019</xref>, <xref ref-type="bibr" rid="B4">2021</xref>)&#x02014;a framework that we developed to integrate Big Data management platforms (RAM3S stands for Real-time Analysis of Massive MultiMedia Streams)&#x02014;has evolved int SPAF, a Stream Processing Abstracting Framework. The use of SPAF makes much easier, for researchers, to implement real-time complex analyses of massive MM streams exploiting a distributed computing environment, without specific knowledge of the underlying stream processing distributed infrastructure.</p>
<p>After introducing the running example that will be exploited throughout the paper to illustrate RAM3S/SPAF concepts (Section 2), we will briefly describe the scenario that originally led us to introduce RAM3S and present its current structure (Section 3). The key concepts in SPAF are illustrated in Section 4, while Section 5 provides details on how the stream processing model considered by SPAF can be extended to deal with Direct Acyclic Graph topologies. We will then proceed to analyze the time/space overhead of the SPAF framework (Section 6) and to discuss some of the developments we are working on to be included in the next SPAF release (Section 7). Finally, Section 8 concludes, by also providing a multi-variable analysis of SPAF.</p></sec>
<sec id="s2">
<title>2. Running example: face recognition</title>
<p>In May 2023, Italy&#x00027;s Interior Minister Matteo Piantedosi, interviewed by a national newspaper, claimed that the Italian government was &#x0201C;considering an extensive video surveillance system with facial recognition capabilities&#x0201D; to be deployed in &#x0201C;in highly frequented places&#x0201D; such as stations, hospitals, and commercial areas, in order to contrast the (at the moment) recent rise of crimes and acts of violence.<xref ref-type="fn" rid="fn0001"><sup>1</sup></xref> Besides the obvious concerns about the privacy of citizens and its trade-off with their security/safety, the proposal was also interesting for its impact on the technological infrastructure of smart cities. Indeed, in this application, several cameras are disseminated in the territory (airports, metro stations, public buildings, and so on), producing videos. In order to provide automatic facial recognition, each video has to be first streamed as a sequence of frames and each incoming frame analyzed to:</p>
<list list-type="simple">
<list-item><p>(1) Verify if it contains a face;</p></list-item>
<list-item><p>(2) Compare the (possibly) discovered face against a number of &#x0201C;known&#x0201D; faces, to retrieve the known face most similar to the input face;</p></list-item>
<list-item><p>(3) The face is regarded as correctly recognized if there is a high enough similarity score between the newly discovered face and its most similar known face; otherwise, it is regarded as an unknown face.</p></list-item>
</list>
<p>Since performing all above tasks within the camera itself would require expensive hardware (as well as a way to upload &#x0201C;known&#x0201D; faces), solutions based on edge computing can be hardly applied. Rather, a data infrastructure has to be devised to (1) send videos from cameras to a data processing platform and (2) to analyze such videos on the platform as previously illustrated (see <xref ref-type="fig" rid="F1">Figure 1</xref>). The amount of data coming from several thousands of cameras around Italy would clearly prevent the use of a centralized platform. On the contrary, distributed computing can be of help, because every single frame might be analyzed independently of the others, so that processing of incoming videos could be performed in parallel.</p>
<fig id="F1" position="float">
<label>Figure 1</label>
<caption><p>Face recognition use case.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0001.tif"/>
</fig>
<p>Automatic facial identification in videos was the first application of RAM3S that we created (Bartolini and Patella, <xref ref-type="bibr" rid="B2">2018</xref>).<xref ref-type="fn" rid="fn0002"><sup>2</sup></xref> For this use case, we exploited the well-known Viola&#x02013;Jones algorithm (Viola and Jones, <xref ref-type="bibr" rid="B17">2001</xref>) for face detection, while comparisons of &#x0201C;faces&#x0201D; was performed using a technique based on principal component analysis using eigenfaces (Turk and Pentland, <xref ref-type="bibr" rid="B16">1991</xref>). Clearly, one could consider using different techniques for face detection/recognition, with different precision and time complexity: The use of any particular algorithm is independent on how the computation is distributed on the processing platform, which is oblivious of the tasks it performs.</p>
<p>For the purpose of suspect identification, every time a detected face is sufficiently similar to one of the faces in the knowledge base, the prototype we implemented to illustrate the use of RAM3S raises an alarm. This is also reflected in the prototype GUI (see <xref ref-type="fig" rid="F2">Figure 2</xref>), which outputs incoming images with a frame enclosing each detected face with color red (if recognized) or green (not recognized).</p>
<fig id="F2" position="float">
<label>Figure 2</label>
<caption><p>The GUI of the suspect face detection RAM3S prototype: the left person is correctly recognized (&#x0201C;mpatella,&#x0201D; included in the face DB), the right person is correctly unrecognized (not included in the face DB).</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0002.tif"/>
</fig>
<p>We will use the face recognition use case presented here in the remainder of the paper to instantiate many RAM3S (and SPAF) components. In this way, we will provide concrete form to abstract concepts, so as to improve their comprehensibility to the reader.</p></sec>
<sec id="s3">
<title>3. Introducing RAM3S</title>
<p>Our experience with Big Data streaming analysis platforms derives from a private-financed project focused on the analysis of multimedia streams for security purposes. The private company already had an experience in Big Data <italic>batch processing</italic>, through the long term use of tools such as Hadoop (<ext-link ext-link-type="uri" xlink:href="http://hadoop.apache.org">http://hadoop.apache.org</ext-link>) and Spark (<ext-link ext-link-type="uri" xlink:href="http://spark.apache.org">http://spark.apache.org</ext-link>). However, it was clear that the use of such technologies was inappropriate for a number of security tasks, such as face detection for the automatic identification of &#x0201C;suspect&#x0201D; people (Turk and Pentland, <xref ref-type="bibr" rid="B16">1991</xref>), recognition of suspicious behavior from videos (Mu et al., <xref ref-type="bibr" rid="B8">2016</xref>), human actions (Zhang et al., <xref ref-type="bibr" rid="B19">2016</xref>) or gesture (Roh and Lee, <xref ref-type="bibr" rid="B13">2015</xref>), audio events (&#x00141;opatka et al., <xref ref-type="bibr" rid="B7">2016</xref>), and so on. Indeed, in such <italic>online</italic> applications, data have to be analyzed as soon as these are available, so as to exploit their &#x0201C;freshness.&#x0201D; The storing of incoming data is, thus, usually unnecessary and the efficiency of the system depends on the amount of data processed, keeping low latency, at the second, or even millisecond, level.</p>
<p>To deal with this (at the time) novel <italic>stream processing</italic> paradigm other Big Data platforms were introduced, among which Storm (<ext-link ext-link-type="uri" xlink:href="http://storm.apache.org">http://storm.apache.org</ext-link>), Flink (<ext-link ext-link-type="uri" xlink:href="http://flink.apache.org">http://flink.apache.org</ext-link>), and the streaming version of Spark. Abstracting by specificities of each Stream Processing Engine (SPE) [see Zaharia et al. (<xref ref-type="bibr" rid="B18">2010</xref>) and Alexandrov et al. (<xref ref-type="bibr" rid="B1">2014</xref>) for details on Spark and Flink, respectively], the following common characteristics can be discovered [see also Bartolini and Patella (<xref ref-type="bibr" rid="B2">2018</xref>) for a more detailed comparison of the SPEs originally considered in RAM3S]:</p>
<list list-type="bullet">
<list-item><p>Some nodes in the architecture are in charge of receiving the input data stream, thus containing the data acquisition logic (these are called Receivers in Spark, Spouts in Storm, and Producers in Flink).</p></list-item>
<list-item><p>Other nodes perform the actual data processing (these are called Drivers in Spark, Bolts in Storm, and Task Nodes in Flink).</p></list-item>
<list-item><p>Finally, data sources and data processing nodes are connected to realize the data processing architecture, which takes the form of a Directed Acyclic Graph, where arcs represent the data flow between nodes (in Storm, such architecture is termed Topology).</p></list-item>
</list>
<p>We were, therefore, challenged to implement a number of security-related use-cases on top of such SPEs, with the goal of comparing them by way of several performance KPI, such as throughput, scalability, latency, etc. This required to re-implement every multimedia stream analysis application on top of each SPE, leading to huge code replication and other inefficiencies. For this, we considered realizing a middleware software framework to allow users to:</p>
<list list-type="simple">
<list-item><p>(1) avoid having to deal with details of each specific SPE (such as how fault-tolerance is achieved, how stream data are stored, etc.), and</p></list-item>
<list-item><p>(2) easily extend already available (centralized) software to a <italic>scaled out</italic> solution.</p></list-item>
</list>
<p>This way, we strove to bridge the technological gap between facilities provided by SPEs and advanced applications (for which transition to a distributed computing scenario might not be straightforward). RAM3S represents, as far as we know, the only attempt to provide a general perspective on the analysis of massive multimedia streams, providing the programmer with an abstract view hiding details and complexity of distributed computing.</p>
<sec>
<title>3.1. RAM3S: <italic>almost</italic> a framework</title>
<p>Our original goal for RAM3S was to create a <italic>framework</italic>, according to the definition provided in Gamma et al. (<xref ref-type="bibr" rid="B6">1995</xref>):</p>
<disp-quote><p>&#x0201C;<italic>A</italic> <bold><italic>framework</italic> </bold><italic>is a set of cooperating classes that make up a reusable design for a specific class of software&#x02026;You customize a framework to a particular application by creating application-specific subclasses of abstract classes from the framework.&#x0201D;</italic></p></disp-quote>
<p>A framework, therefore, determines the overall architecture of an application and focuses on the <italic>reusability</italic> of a solution architecture, exposing to application programmers only parameters necessary to realize the desired behavior, as enacted through the internal mechanisms of the framework itself. Applications developed on a framework have therefore some degrees of freedom, that must be however provided by the framework a-priori. For this latter reason, it is of paramount importance that the framework is also characterized by <italic>extensibility</italic>, since it is practically impossible to predict all the needs of concrete applications in advance; this way, the framework will be able to better withstand the test of time, since it can eventually evolve through possible future integrations.</p>
<p>The current version of RAM3S allows to experiment with the various SPEs (namely, Spark Streaming, Storm, Flink, and Samza) by providing a separate &#x0201C;generic&#x0201D; application for each of them. Each of such applications allows the execution of the specific example on the respective SPE. RAM3S interposes an abstraction layer based on interfaces between the generic and the example applications. Such interfaces model aspects of both data streaming and data processing:</p>
<list list-type="bullet">
<list-item><p>The <monospace>Receiver</monospace> interface represents the external system from which the application receives data. The <monospace>receive</monospace> method accommodates the logic of receiving the single processable object from the external system.</p></list-item>
<list-item><p>The <monospace>Analyzer</monospace> interface represents the container of all the processing logic of the application: its <monospace>analyze</monospace> methods takes a MM object as input, generating a single object as result.</p></list-item>
<list-item><p>Finally, the <monospace>ApplicationFactory</monospace> interface is responsible for representing the application as a unit; in essence, it serves as a collector for the <monospace>Analyzer</monospace> implementation and for the <monospace>Receiver</monospace> implementation, by instantiating the concrete <monospace>Analyzer</monospace> and <monospace>Receiver</monospace> type classes defined in the application context.</p></list-item>
</list>
<p><xref ref-type="fig" rid="F3">Figure 3</xref> illustrates (<xref ref-type="fig" rid="F3">Figure 3A</xref>) the relationships between RAM3S interfaces and (<xref ref-type="fig" rid="F3">Figure 3B</xref>) how these are implemented for the face detection example.</p>
<fig id="F3" position="float">
<label>Figure 3</label>
<caption><p>RAM3S programming interface <bold>(A)</bold> and its instantiation for the face recognition application <bold>(B)</bold>.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0003.tif"/>
</fig>
<p>Let us now consider how RAM3S interfaces are used by generic applications. The purpose of a generic application is to map the application (defined in terms of the above interfaces) to the relevant SPE, therefore executing its logic on the underlying runtime framework. The class diagram in <xref ref-type="fig" rid="F4">Figure 4</xref> contextualizes the RAM3S generic applications with respect to the various stream processing engines considered in RAM3S.</p>
<fig id="F4" position="float">
<label>Figure 4</label>
<caption><p>RAM3S generic applications for all included stream processing engines.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0004.tif"/>
</fig>
<p>Generic application code is always completely specified within the <monospace>main</monospace> method and has a recurring structure, presented in <xref ref-type="fig" rid="F5">Figure 5</xref>.</p>
<fig id="F5" position="float">
<label>Figure 5</label>
<caption><p>Code of RAM3S for the face recognition application.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0005.tif"/>
</fig>
<p>The concrete factory is used to create the <monospace>Receiver</monospace> and <monospace>Analyzer</monospace>; then, such objects have to be translated into objects and procedures specific of the underlying SPE, as exposed by its APIs; the purpose of this step is to concretely establish the connection to the specific data processing infrastructure and to implement the application logic. Clearly, this is so-called boilerplate code, peculiar to the underlying SPE, that has to be repeated, almost verbatim, for each specific application. Moreover, code specific for a single application is repeated (again, almost verbatim) over the <monospace>main</monospace> method of any used SPE.</p>
<p>A final component of RAM3S is the one used to support different message brokers (Bartolini and Patella, <xref ref-type="bibr" rid="B4">2021</xref>). The abstraction layer devoted to message brokers consists of the <monospace>messageBroker</monospace> package shown in <xref ref-type="fig" rid="F6">Figure 6</xref>. This package includes interfaces for the abstract representation of &#x0201C;readers&#x0201D; and &#x0201C;writers&#x0201D; (<monospace>Reader</monospace> and <monospace>Writer</monospace> interfaces) and concrete classes for the implementation of interfaces for a specific message broker (the figure reports only those for Apache Kafka, i.e., <monospace>KafkaReader</monospace> and <monospace>KafkaWriter</monospace>). For each stream processing engine (<xref ref-type="fig" rid="F6">Figure 6</xref> depicts the example of Flink), an additional layer is needed to map the above <monospace>Reader</monospace> and <monospace>Writer</monospace> concrete classes into, respectively, the source and destination of data processed by the application.</p>
<fig id="F6" position="float">
<label>Figure 6</label>
<caption><p>RAM3S support for message brokers.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0006.tif"/>
</fig>
<p>From the analysis we have presented, we can conclude that, at present, RAM3S allows different stream processing applications to be executed in a facilitated manner, but is not yet able to allow the definition of a new application without having to write part of the code of RAM3S itself. This drawback places RAM3S in the role of a &#x0201C;quasi-framework.&#x0201D; On the other hand, the message broker support is independent of the application code (thus satisfying the reusability requirement) and makes it possible to decouple the implementation of the read and write &#x0201C;adapters&#x0201D; of a certain message broker from the underlying stream processing engine (thus also offering extensibility). In the next section, we will introduce SPAF, whose main goal is to enable the use of RAM3S according to the original intent, namely to facilitate the creation of new stream processing applications, while striving for both reusability and extensibility.</p></sec>
</sec>
<sec id="s4">
<title>4. From RAM3S to SPAF</title>
<p>Before describing the concepts that have been used to define our Stream Processing Abstraction Framework, SPAF, it is useful to recollect the original requirements for RAM3S:</p>
<list list-type="simple">
<list-item><p><bold>Facilitate the creation of stream processing applications:</bold> the SPAF API should explicitly expose the pivotal concepts of stream processing and, more importantly, allow the application to be defined by writing code as close as possible to a description in natural language. Checking type-safety at compile time would be also helpful.</p></list-item>
<list-item><p><bold>Framework independence:</bold> here, the target user is not the programmer of applications, rather the developer who wants to extend SPAF to work with a different SPE. Such programming interface is called Service Provider Interface (SPI) and is a programming pattern supported natively by Java.</p></list-item>
<list-item><p><bold>Connector independence:</bold> it should be possible to integrate, in a pluggable manner, new connector providers (e.g., message queues, file systems, databases), again exposing a SPI to be implemented by developers. SPAF will therefore expose a dual abstraction layer: one for SPEs and one for input/output supports. Connector abstraction actually concerns the application programmer as well, since the SPAF API should relieve the programmer of the implementation details regarding the use of each connector&#x00027;s libraries and allow her to specify sources and destinations in a declarative manner.</p></list-item>
</list>
<sec>
<title>4.1. Simplifying assumptions</title>
<p>In the first version of SPAF, a number of simplifying assumptions has been introduced to ease implementation of the previously described requisites:</p>
<list list-type="simple">
<list-item><p>(1) Connectors will be limited to message queues, as provided by well-known message brokers such as Apache Kafka and RabbitMQ.</p></list-item>
<list-item><p>(2) Streams will be composed exclusively by key-value pairs.</p></list-item>
<list-item><p>(3) No support will be provided for storing intermediate computation results, i.e., stream processing will be stateless.</p></list-item>
<list-item><p>(4) The processors operating transformations on streams will accept a single input stream and a single output stream; essentially, it will be possible to define only &#x0201C;linear&#x0201D; topologies.</p></list-item>
<list-item><p>(5) It will be possible to specify only the logical topology (definition of the transformation process from input to output) and not the physical topology (definition of how various computational elements of the logical topology&#x02014;sources, transformation operators, destinations&#x02014;are to be distributed on the physical nodes).</p></list-item>
</list>
<p>Assumption 1 can be easily overcome by providing tools (e.g., a command-line script) able of reading data to be processed from the desired source type (e.g., an input file) and publishing them to an appropriate input queue; likewise, it is possible to implement scripts able of consuming messages from the output queue and store them on the desired destination (e.g., a database). As for Assumption 3, our choice was to favor generality and simplicity over completeness. Indeed, not all SPEs might support stateful computation (for example, Storm does not) and those that support it introduce several other concepts that would complicate the SPAF model of stream processing. Although this version of SPAF does not include formal, integrated support for storing (globally or locally) intermediate results of individual transformation nodes, nothing prevents the programmer to implement access to storage resources external to the framework (e.g., files, DBs, object caches) in the transformation logic defined in the processing nodes, i.e., the programmer is responsible for implementing support for stateful computation. In this way, complex algorithms for analyzing multiple objects, like interval joins (Piatov et al., <xref ref-type="bibr" rid="B11">2021</xref>), can be mapped to single processing nodes that are part of a more complex topology, performing other analyses (like image processing and/or event detection) on data streams (Persia et al., <xref ref-type="bibr" rid="B10">2017</xref>). While a possible solution to overcome Assumption 4 will be described in Section 5, Assumption 5 can be partially solved by connecting multiple independent RAM3S applications by way of appropriate connectors; in this way, each logical topology would be mapped to a physical topology (defined automatically by, and peculiar of, the SPE chosen for each RAM3S application). Since this so-called <italic>super-</italic>topology can assume the form of a Direct Acyclic Graph (DAG), this can also be viewed as a solution to Assumption 4.</p>
</sec>
<sec>
<title>4.2. SPAF architecture</title>
<p><xref ref-type="fig" rid="F7">Figure 7</xref> shows the general architecture of SPAF. The application programmers will use the <italic>user-facing</italic> API to implement their stream processing application using Java code. Developers wanting to extend SPAF to include new SPEs (or connectors) will use the <italic>provider-facing</italic> SPI to write the <italic>glue code</italic> that allows bridging SPAF concepts to those peculiar to the SPE.</p>
<fig id="F7" position="float">
<label>Figure 7</label>
<caption><p>SPAF architecture.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0007.tif"/>
</fig>
</sec>
<sec>
<title>4.3. SPAF concepts</title>
<p>The first step in the definition of SPAF was to provide a general model of the stream processing problem, thus defining a set of entities that are common to all SPEs (see <xref ref-type="fig" rid="F8">Figure 8</xref>).</p>
<fig id="F8" position="float">
<label>Figure 8</label>
<caption><p>Main SPAF classes and interfaces.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0008.tif"/>
</fig>
<p>The <monospace>Context</monospace> entity represents the actual execution environment in which the abstractly defined application will be implemented. This therefore acts as a &#x0201C;bridge&#x0201D; between the abstract SPAF world and the concrete world made available by SPEs. The <monospace>run</monospace> method of the <monospace>Context</monospace> class is the &#x0201C;entry point&#x0201D; of the stream processing application, just like the <monospace>main</monospace> method of a Java class. Through the <monospace>run</monospace> method, we submit as a parameter the application, defined in terms the SPAF API to the underlying SPE; the SPE will then &#x0201C;interpret&#x0201D; the application, &#x0201C;translating&#x0201D; it into an equivalent representation using its specific concepts. Implementation of the <monospace>Context</monospace> is thus totally peculiar to each SPE; for this, the class <monospace>Config</monospace> allows the programmer to configure the execution environment in an abstract way (on the API side) and to implement such configurations in a provider-specific way (on the SPI side).</p>
<p>A <monospace>Topology</monospace> defines the computational logic of a stream processing application, that is, how the input data are transformed into the output data. As said, in the first version of SPAF only linear topologies are supported. We conceived the framework to accept specifications of the logic of <monospace>Processor</monospace> nodes also via lambda-functions and present a <italic>fluent</italic> API to compose the topology. To achieve this, we exploited a &#x0201C;creational-type&#x0201D; design pattern called <italic>Builder</italic>, allowing complex objects (like a topology) to be constructed step by step; this could also re-used in future versions of SPAF, where it may be convenient to change the way the topology is represented (e.g., to encompass DAG topologies).</p>
<p>The concept of <monospace>Application</monospace> basically coincides with the one of <monospace>Topology</monospace>, essentially adding descriptive information only. Conceptually, however, a stream processing application could define more than one topology: this is why the two entities are separated, although, in this first version of SPAF, there is a 1-1 relationship between <monospace>Application</monospace> and <monospace>Topology</monospace>.</p>
<p><monospace>Source</monospace> and <monospace>Sink</monospace> clearly denote the source and destination, respectively, for data in a stream processing application.</p>
<p>A <monospace>Processor</monospace> represents a node in the <monospace>Topology</monospace>, implementing a processing step that is used to transform data, thus realizing the actual data processing logic. <monospace>Processor</monospace>s can be thought as &#x0201C;black boxes&#x0201D; with a single input and a single output stream, where data transformation can be defined arbitrarily through the <monospace>process</monospace> method. The additional <monospace>init</monospace> method can be defined in those cases needing a one-off initialization of the <monospace>Processor</monospace>.</p>
<p>Finally, the <monospace>Element</monospace> entity represents the only data type that can be streamed in a SPAF <monospace>Topology</monospace>. The <monospace>Element</monospace> class is somewhat hidden from the application programmer, while its use appears evident in the SPI layer, for both SPEs and connectors.</p>
<p>We finally provide in <xref ref-type="table" rid="T1">Table 1</xref> a mapping between SPAF concepts and those encountered in the considered SPEs.</p>
<table-wrap position="float" id="T1">
<label>Table 1</label>
<caption><p>Mapping between SPAF and SPE concepts.</p></caption> 
<table frame="box" rules="all">
<thead>
<tr style="background-color:&#x00023;919498;color:&#x00023;ffffff">
<th valign="top" align="left" colspan="2"><bold>SPAF</bold></th>
<th valign="top" align="left"><bold>Apache Samza</bold></th>
<th valign="top" align="left"><bold>Apache Flink</bold></th>
<th valign="top" align="left"><bold>Apache Storm</bold></th>
<th valign="top" align="left"><bold>Apache Spark</bold></th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top" align="left" rowspan="2"><monospace>Context</monospace></td>
<td valign="top" align="left"><italic>Local</italic></td>
<td valign="top" align="left"><monospace>LocalApplicationRunner</monospace> </td>
<td valign="top" align="left"><monospace>LocalStreamEnvironment</monospace> </td>
<td valign="top" align="left"><monospace>LocalCluster</monospace> </td>
<td valign="top" align="left"><monospace>JavaStreamingContext</monospace> </td>
</tr>
<tr>
<td/>
<td valign="top" align="left"><italic>Remote</italic></td>
<td valign="top" align="left"><monospace>RemoteApplicationRunner</monospace> </td>
<td valign="top" align="left"><monospace>RemoteStreamEnvironment</monospace> </td>
<td valign="top" align="left"><monospace>StoreSubmitter</monospace> </td>
<td valign="top" align="left"><monospace>JavaStreamingContext</monospace> </td>
</tr> <tr>
<td valign="top" align="left" colspan="2"><monospace>Application</monospace> </td>
<td valign="top" align="left"><monospace>TaskApplicationDescriptor</monospace> </td>
<td valign="top" align="left"><monospace>StreamExecutionEnvironment</monospace> </td>
<td valign="top" align="left"><monospace>LocalCluster</monospace><break/><monospace>StoreSubmitter</monospace> </td>
<td valign="top" align="left"><monospace>JavaStreamingContext</monospace> </td>
</tr> <tr>
<td valign="top" align="left" rowspan="2"><monospace>Topology</monospace></td>
<td valign="top" align="left"><italic>Logical</italic></td>
<td/>
<td valign="top" align="left"><monospace>StreamGraph</monospace> </td>
<td valign="top" align="left"><monospace>StormTopology</monospace> </td>
<td valign="top" align="left"><monospace>DStreamGraph</monospace> </td>
</tr>
<tr>
<td/>
<td valign="top" align="left"><italic>Physical</italic></td>
<td valign="top" align="left"><monospace>StreamTask</monospace> </td>
<td valign="top" align="left"><monospace>JobGraph</monospace> </td>
<td valign="top" align="left"><monospace>Task</monospace> </td>
<td/>
</tr> <tr>
<td valign="top" align="left" colspan="2"><monospace>Element</monospace> </td>
<td valign="top" align="left"><monospace>Object</monospace> </td>
<td valign="top" align="left"><monospace>Tuple0,</monospace> <monospace>&#x02026;, 25 &#x0003C; T&#x0003E;</monospace><break/><monospace>DataStream &#x0003C; T&#x0003E;</monospace> </td>
<td valign="top" align="left"><monospace>Tuple</monospace> </td>
<td valign="top" align="left"><monospace>DStream &#x0003C; T&#x0003E;</monospace> </td>
</tr> <tr>
<td valign="top" align="left" colspan="2"><monospace>Source</monospace> </td>
<td valign="top" align="left"><monospace>InputDescriptor</monospace> </td>
<td valign="top" align="left"><monospace>SourceFunction &#x0003C; T&#x0003E;</monospace> </td>
<td valign="top" align="left"><monospace>Spout</monospace> </td>
<td valign="top" align="left"><monospace>InputDStream</monospace> </td>
</tr> <tr>
<td valign="top" align="left" colspan="2"><monospace>Processor</monospace> </td>
<td valign="top" align="left"><monospace>StreamTask::process()</monospace> </td>
<td valign="top" align="left"><monospace>ProcessFunction::</monospace><break/><monospace>processElement()</monospace> </td>
<td valign="top" align="left"><monospace>Bolt</monospace> </td>
<td valign="top" align="left"><monospace>DStream</monospace> methods</td>
</tr>
<tr>
<td valign="top" align="left" colspan="2"><monospace>Sink</monospace> </td>
<td valign="top" align="left"><monospace>OutputDescriptor</monospace> </td>
<td valign="top" align="left"><monospace>SinkFunction &#x0003C; T&#x0003E;</monospace> </td>
<td valign="top" align="left"><monospace>Bolt</monospace> </td>
<td valign="top" align="left"><monospace>DStream::foreachRDD()</monospace> </td>
</tr>
</tbody>
</table>
</table-wrap>
</sec>
<sec>
<title>4.4. Developing an application using SPAF</title>
<p>To create an application in SPAF, it is necessary to follow some steps, mostly independent of the specific streaming application logic to be created. In the following, we will exemplify the creation of an application for the &#x0201C;face recognition in videos&#x0201D; example introduced in Section 2. What we want to prove with this &#x0201C;experiment&#x0201D; is that SPAF is indeed able to satisfy the requirements listed in Section 4, i.e., framework and connector independence and ease of creation of the application. As it will be clear, the application-specific code can be easily distinguished from the generic SPAF-based application code.</p>
<p>The code needed for the complete specification of a SPAF application has actually a dual nature:</p>
<list list-type="bullet">
<list-item><p>Some <italic>declarative</italic> code, included in a configuration file, needed to specify the customization of SPAF entities, like <monospace>Context</monospace>, <monospace>Source</monospace>, or <monospace>Sink</monospace>.</p></list-item>
<list-item><p>Some <italic>procedural</italic> code, used to instantiate SPAF classes and to specify the actual stream processing application logic; this is included in the <monospace>main</monospace> method of the application and, again, is mainly boilerplate code.</p></list-item>
</list>
<p>For the specific use case, a possible config file is shown in <xref ref-type="fig" rid="F9">Figure 9</xref>, where one can recognize the specification of the context (using Flink as SPE) of the application, and of the input and output connectors (using Kafka).</p>
<fig id="F9" position="float">
<label>Figure 9</label>
<caption><p>Configuration file for the SPAF face recognition application.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0009.tif"/>
</fig>
<p>Finally, the <monospace>FaceRecognition</monospace> application includes a <monospace>main</monospace> method with the code included in <xref ref-type="fig" rid="F10">Figure 10</xref>.</p>
<fig id="F10" position="float">
<label>Figure 10</label>
<caption><p><monospace>main</monospace> method for the SPAF face recognition application.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0010.tif"/>
</fig>
<p>The goals of independence on frameworks and connectors are demonstrated by the fact that it is quite easy to change the configuration file to encompass different SPEs (in the <monospace>context</monospace> section) or connectors (<monospace>source</monospace> and <monospace>sink</monospace> sections). As to the creation of stream processing applications, it is clear that most of the procedural code is indeed boilerplate, i.e., repeated with no variation across different applications. The only specific part is at Step 3, where we specify that this application is composed of three main phases: (1) detection of faces in each image, (2) recognition of detected faces, and (3) (possible) marking of recognized faces (note that these correspond exactly with the three steps illustrated in Section 2). Obviously, the programmer should also write the code for each individual <monospace>Processor</monospace> (<xref ref-type="fig" rid="F11">Figure 11</xref> shows the example for the <monospace>FaceRecognitionProcessor</monospace>), but this is absolutely independent of the underlying stream processing infrastructure (following the original goal of RAM3S). Step 3 also demonstrates the use of the Builder pattern, where each <monospace>Processor</monospace> refers to its predecessor through its id.</p>
<fig id="F11" position="float">
<label>Figure 11</label>
<caption><p>Implementation of a <monospace>Processor</monospace> in SPAF.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0011.tif"/>
</fig>
<p>A dimension of fundamental importance, which should be taken into account when choosing any development tool, is the so-called &#x0201C;learning curve&#x0201D;, which relates the level of knowledge and the time invested in learning a new thing. SPAF plays the role of the &#x0201C;guide&#x0201D; that takes the programmer through the discovery of stream processing concepts, providing a logical path that facilitates their understanding and thus making the learning curve of stream processing less daunting. SPAF is therefore able to make life easier for the inexperienced programmer who must venture into the world of stream processing for the first time, and make that journey less treacherous (like Virgil, accompanying Dante through the &#x0201C;hell&#x0201D; of stream processing).</p></sec>
</sec>
<sec sec-type="discussion" id="s5">
<title>5. Discussion</title>
<p>In this section, we want to highlight two interesting concepts, both related to the constructions of DAG-shaped topologies, namely the SPAF representation of topologies and the so-called <italic>super-topologies</italic>.</p>
<p>When considering the representation of topologies in SPAF, we should remind that the key operation for a topology is how the SPAF stream processing layer (see <xref ref-type="fig" rid="F7">Figure 7</xref>) is able to map the <monospace>Topology</monospace> entity in the corresponding topology of the underlying SPE (who will then autonomously map it to a physical topology on computing nodes). Since this version of SPAF only accepts linear topologies, this mapping is extremely simple, being implemented as a loop visiting all nodes of the topology in an ordered way (see <xref ref-type="fig" rid="F12">Figure 12</xref>).</p>
<fig id="F12" position="float">
<label>Figure 12</label>
<caption><p>Mapping topologies.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0012.tif"/>
</fig>
<p>Refactoring the <monospace>Source</monospace>, <monospace>Processor</monospace>, and <monospace>Sink</monospace> entities (see <xref ref-type="fig" rid="F8">Figure 8</xref>), currently used to build topologies, an abstract entity <monospace>TopologyNode</monospace> could be created, exposing a common interface. In this way, <monospace>Source</monospace>s, <monospace>Processor</monospace>s, and <monospace>Sink</monospace>s could be considered as <monospace>TopologyNode</monospace> instances, allowing to use polymorphism to implement simple (and elegant) algorithms for mapping topologies, e.g., by exploiting a <italic>Visitor</italic> pattern based on a topological sort of the DAG.</p>
<p>Finally, we consider the use of multiple SPAF applications, in a simultaneous and coordinated manner, with the aim of solving a stream processing problem in a &#x0201C;highly distributed manner&#x0201D; (we will soon clarify what we mean by this adjective). The main idea is based on the decomposition of the stream processing problem into sub-problems, and in solving them through the use of multiple, independent but cooperative, SPAF projects. Each SPAF application will define a certain logical topology able of solve a certain sub-problem; each topology will receive data via the connectors provided by SPAF, process them, and send the processed data back to the outside world. In this scenario, message queues are used as means of communication between the topologies of individual projects. In other words, we can implement a topology of topologies (see <xref ref-type="fig" rid="F13">Figure 13</xref>). Individual topologies, in fact, can be thought as &#x0201C;black boxes&#x0201D;, processing nodes of a DAG, receiving and sending data via the arcs connecting them, the latter realized by different message queues. What we just described corresponds precisely to the definition of topology given in Section 4.3, but at a higher level, thus the name of super-topology, where the prefix super- is to be understood in the Latin sense of &#x0201C;that stands above&#x0201D;.</p>
<fig id="F13" position="float">
<label>Figure 13</label>
<caption><p>Super-topologies in SPAF.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0013.tif"/>
</fig>
<p>In the diagram of <xref ref-type="fig" rid="F13">Figure 13</xref>, it is shown how to conceptually realize a SPAF super-topology. It will be necessary to provide &#x0201C;border&#x0201D; sources and sinks (shown in blue and yellow, respectively), functioning as the input and outputs of the entire super-topology. The processing (red) nodes of the super-topology will instead correspond to a single SPAF application each, defining its own <monospace>Source</monospace> and <monospace>Sink</monospace>, and will consist of a (currently, only linear) <monospace>Topology</monospace> of <monospace>Processor</monospace>s. Communication between nodes of the super-topology, i.e., between the various SPAF applications, is realized by way of appropriate message queues between node pairs (these are represented by red arcs in the figure and exemplified on the right). Obviously, each topology will have to be configured to receive and send data to the right message queues, whether they are &#x0201C;border&#x0201D; (in the example, topologies T1, T2, T4, and T5) or &#x0201C;internal&#x0201D; (T3).</p>
<p>The use of super-topologies in SPAF opens up some interesting scenarios:</p>
<list list-type="bullet">
<list-item><p>Each SPAF application, i.e., each node in the super-topology, can be executed by a potentially different SPE, since each application can in fact specify the desired SPAF provider independently from the others.</p></list-item>
<list-item><p>It follows that each SPAF application, i.e., each node of the super-topology, can potentially be executed on a cluster of nodes by itself; for this, we previously used the term &#x0201C;highly distributed&#x0201D; execution.</p></list-item>
</list>
<p>The first version of the SPAF framework does not allow super-topologies to be managed at the API level. Rather, each application is independent of the others and its lifecycle must be managed by the programmer. The implementation of the illustrated scheme thus requires a systemic effort aimed at setting up the clusters of the various SPEs, the arrangement of the messaging systems, the configuration of the connectors, and the coordinated startup of the individual applications. As an interesting extension of SPAF, we are considering the implementation of facilitator tools able of automatically performing the above described tasks.</p></sec>
<sec id="s6">
<title>6. SPAF overhead</title>
<p>It is well known that, often, increased flexibility comes at the price of reduced performance. In this section, we investigate the impact of SPAF on performance of a MM stream analysis application.</p>
<p>A SPAF application is essentially composed of several layers of abstraction, which can be summarized as follows:</p>
<list list-type="simple">
<list-item><p><bold>Application layer:</bold> This is the SPAF application code, defined by the programmer, which consists mainly of the code defining the <monospace>Processor</monospace>s and the <monospace>Topology</monospace>.</p></list-item>
<list-item><p><bold>Interpretation layer:</bold> It is the code of the SPAF framework, consisting of the glue-code contained in the SPAF APIs and, most importantly, the code of the mapping to the employed SPE, translating the application in terms of the underlying framework.</p></list-item>
<list-item><p><bold>Execution layer:</bold> This is the code of the relevant underlying SPE, made usable by the SPAF provider, which actually executes the translated application.</p></list-item>
</list>
<p>The cost required to execute the application, both in terms of used CPU and memory, can be broken down into three components, based on the above layers.</p>
<p>The cost of execution of the Application Layer is totally dependent on the logic of the application. The programmer has total freedom in defining operations within <monospace>Processor</monospace>s, and can use any third-party library. This cost is therefore difficult to predict, but it has to be paid in any case, thus the use of SPAF does not add any extra complexity.</p>
<p>Clearly, the cost of the Execution Layer is also independent of SPAF, and has to be paid in any case. As a matter of fact, one of the original intents of RAM3S was to help the programmer to compare performance of different SPEs in managing a stream processing application. It is obvious that using SPAF does not increase costs.</p>
<p>It follows that the only cost component imputable to SPAF is the one coming from the Interpretation Layer, translating the SPAF application to an application of the underlying SPE. This cost is clearly paid only once, when the SPAF application is started, and it consists in:</p>
<list list-type="simple">
<list-item><p>(1) translating the application, written with SPAF concepts, using concepts of the underlying SPE, and</p></list-item>
<list-item><p>(2) visiting the topology.</p></list-item>
</list>
<p>The first cost clearly is traded with the steepness of the learning curve, as stated in Section 4.4. If we concur that writing an application with SPAF is easier than using the original SPE, this comes at the cost of translating concepts between frameworks. The second cost is paid at runtime and can be further divided into three steps:</p>
<list list-type="simple">
<list-item><p>(1) iterating through the topology,</p></list-item>
<list-item><p>(2) translating each visited <monospace>Processor</monospace> to the underlying SPE, and</p></list-item>
<list-item><p>(3) executing the topology in the underlying SPE.</p></list-item>
</list>
<p>Steps 2 and 3 have a constant time complexity for each element, while Step 1 has a linear time complexity (this is obvious for linear topologies considered in this version of SPAF, but also with DAG topologies if we exploit a Visitor pattern as stated in Section 5). As to space complexity, since each topology component needs translation, this is again linear in the number of nodes of the topology.</p></sec>
<sec id="s7">
<title>7. Further developments</title>
<p>In this section, we discuss three further directions that we are considering to include in next SPAF versions: support for (1) JMS connectors, (2) configuration of the physical topology, and (3) automatic code generation through a Domain Specific Language (DSL).</p>
<sec>
<title>7.1. JMS connectors</title>
<p>As we detailed in Section 3.1, RAM3S already included support for different message brokers (namely, Apache Kafka and RabbitMQ) and these have been inherited by SPAF in the <monospace>Source</monospace> and <monospace>Sink</monospace> interfaces, providing descriptors for both connector providers (see <xref ref-type="fig" rid="F14">Figure 14</xref> for details).</p>
<fig id="F14" position="float">
<label>Figure 14</label>
<caption><p>Class diagram for a connector provider descriptor (in the example, Kafka).</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0014.tif"/>
</fig>
<p>The difficult part in implementing a new connector in SPAF lies mainly on the provider side, since this strongly depends on the peculiarities of SPE, rather than on the message broker that one wants to connect. Implementation of a connector descriptor, on the other hand, is relatively straightforward, since it is essentially a matter of deciding which configurations have to be made available and how to represent such configurations as objects. With this in mind, it becomes apparent that the implementation of connectors for new message broker type systems can be an onerous task, thus making SPAF difficult to extend on this side. One possible way to drastically reduce the number of connectors to be realized, of both descriptive and concrete types, is to exploit the JMS [Jakarta (or Java) Messaging Service] abstraction framework.<xref ref-type="fn" rid="fn0003"><sup>3</sup></xref> In a nutshell, JMS is an abstraction framework for using message-queue systems. To draw a parallel, we could say that SPAF stands to SPEs as JMS stands to message-queue systems. Most of the message-queue systems (including Apache Kafka and RabbitMQ) implement the JMS provider; it follows that, by realizing a single connector for JMS, SPAF would turn out to be potentially linkable to any message-queue system. If the message broker one intends to use does not include a JMS provider, it would be always possible to autonomously implement such a provider, since JMS is an open specification.</p>
</sec>
<sec>
<title>7.2. Physical topology configuration</title>
<p>A number of SPEs (like Storm and Flink) allow the programmer to control the degree of parallelism in the execution of the logical topology. This allows to determine the structure of the corresponding physical topology, in particular specifying the number of physical nodes (<italic>tasks</italic>) to be provided for performing the computation specified in a unique node of the logical topology (the SPAF <monospace>Processor</monospace>). The degree of parallelism can be specified at different levels of granularity, ranging from: system level (for all applications), individual application level (for a single <monospace>Application</monospace>), or individual operator (the single <monospace>Processor</monospace>).</p>
<p>In the current version of SPAF, implemented providers do not allow to change the degree of parallelism at the level of the individual operator. SPAF APIs do not allow to specify such information, thus parallelism could only be set, in a totally arbitrary manner, for all operators. A possible future development of SPAF, which we are considering in order to allow fine tuning performance of a stream processing application at runtime, would require to expose the ability to specify the desired degree of parallelism for each <monospace>Source</monospace>, <monospace>Sink</monospace>, and <monospace>Processor</monospace>, at the API level. A possible means of implementation to realize this could be that of using language metadata that can be inspected at runtime, like Java Annotations (see <xref ref-type="fig" rid="F15">Figure 15</xref> for a possible example).</p>
<fig id="F15" position="float">
<label>Figure 15</label>
<caption><p>Definition of a Java annotation for specifying the degree of parallelism.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0015.tif"/>
</fig>
<p>Such a defined annotation could be specified for each <monospace>Processor</monospace> as in the following, where we illustrate the case of the <monospace>FaceRecognitionProcessor</monospace> described in <xref ref-type="fig" rid="F11">Figure 11</xref>.</p>
<preformat>&#x000A0;
&#x00040;ExecutionHints(parallelism = 5)
public class FaceRecognitionProcessor implements
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;Processor &#x0003C; ...&#x0003E; {
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x00040;Override
&#x000A0;&#x000A0;&#x000A0;&#x000A0;public void init() { ... }
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x00040;Override
&#x000A0;&#x000A0;&#x000A0;&#x000A0;public void process(...) { ... } }
</preformat>
</sec>
<sec>
<title>7.3. Automating the generation of applications</title>
<p>In the current incarnation of SPAF, to create a new stream processing application, it is necessary to manually perform a series of tasks that are potentially repeated over different projects:</p>
<list list-type="simple">
<list-item><p>(1) writing the boilerplate code for the specific SPAF application,</p></list-item>
<list-item><p>(2) choosing the stream processing provider and connector provider,</p></list-item>
<list-item><p>(3) creating the application configuration files, and</p></list-item>
<list-item><p>(4) deploying the whole application on the computing infrastructure.</p></list-item>
</list>
<p>The open-source community has developed several tools to automate the kinds of of tasks required to prepare a new software project, like Archetypes in Maven (<ext-link ext-link-type="uri" xlink:href="https://maven.apache.org/archetypes/">https://maven.apache.org/archetypes/</ext-link>) or Yeoman Generators (<ext-link ext-link-type="uri" xlink:href="https://yeoman.io/generators/">https://yeoman.io/generators/</ext-link>). However, these tools express their full power when they are coupled with a language used to describe the project in a declarative way. In practice, we are assuming the definition of a <italic>Domain Specific Language</italic> (DSL) for the high-level description of SPAF projects.</p>
<p>To illustrate this idea, we provide an example for the use case of automatic suspect identification from videos introduced in Section 2. The topology illustrated in <xref ref-type="fig" rid="F16">Figure 16</xref> represents an evolution of the current application example for face recognition (see Section 4.4). This new topology provides the possibility of feeding, at runtime, the stream processing application with new faces to be recognized (via the &#x0201C;Suspects Photos&#x0201D; <monospace>Source</monospace>); such faces would be compared by the &#x0201C;Face Recognition&#x0201D; <monospace>Processor</monospace> with images coming from cameras (&#x0201C;Input Photos&#x0201D; <monospace>Source</monospace>), appropriately processed by the &#x0201C;Face Detection&#x0201D; <monospace>Processor</monospace>; the output of this <monospace>Processor</monospace> is then used by two further <monospace>Processor</monospace>s, &#x0201C;Face Marking&#x0201D; (for drawing frames around detected faces in the original image, coloring them differently whether they were recognized or not, see <xref ref-type="fig" rid="F2">Figure 2</xref>) and &#x0201C;Alert Generator&#x0201D; (which would generate a suspicious detection alert); the outputs of these two processors are then sent to two specific <monospace>Sink</monospace>s, &#x0201C;Output Photos&#x0201D; and &#x0201C;Suspect Alerts&#x0201D;, respectively.</p>
<fig id="F16" position="float">
<label>Figure 16</label>
<caption><p>SPAF topology for an application of automatic suspect identification from videos.</p></caption>
<graphic mimetype="image" mime-subtype="tiff" xlink:href="fdata-06-1227156-g0016.tif"/>
</fig>
<p>By using a prototypical idea of DSL, inspired by PlantUML (<ext-link ext-link-type="uri" xlink:href="https://plantuml.com/">https://plantuml.com/</ext-link>), which is the language used to define several figures in this paper, this topology could thus be described as follows:</p>
<preformat>
source InputPhotos
source SuspectsPhotos
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
processor FaceDetection
processor FaceRecognition
processor FaceMarking
processor AlertGenerator
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
sink OutputPhotos
sink SuspectAlerts
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
InputPhotos --&#x0003E; FaceDetection
FaceDetection --&#x0003E; FaceRecognition
SuspectsPhotos --&#x0003E; FaceRecognition
FaceRecognition --&#x0003E; FaceMarking
InputPhotos --&#x0003E; FaceMarking
FaceMarking --&#x0003E; OutputPhotos
FaceRecognition --&#x0003E; AlertGenerator
AlertGenerator --&#x0003E; SuspectAlerts
</preformat>
<p>An interpreter for such a language might take as input a file containing the topology description and invoke the project generator so that a more advanced boilerplate code can be produced wrt the one usually generated with the current version of SPAF (see Section 4.4). Clearly, in addition to the boilerplate code, the generator will have to produce classes to accommodate the implementation code of the <monospace>Processor</monospace>s defined in the topology.</p>
<preformat>
...
Topology topology = new Topology()
&#x000A0;&#x000A0;&#x000A0;.addSource(&#x0201C;InputPhotos&#x0201D;, inputPhotosSource)
&#x000A0;&#x000A0;&#x000A0;.addSource(&#x0201C;SuspectsPhotos&#x0201D;, suspectsPhotosSource)
&#x000A0;&#x000A0;&#x000A0;.addProcessor(&#x0201C;FaceDetection&#x0201D;, new
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;FaceDetectionProcessor(), &#x0201C;InputPhotos&#x0201D;)
&#x000A0;&#x000A0;&#x000A0;.addProcessor(&#x0201C;FaceRecognition&#x0201D;, new
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;FaceRecognitionProcessor(config),
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x0201C;SuspectsPhotos&#x0201D;, &#x0201C;FaceDetection&#x0201D;)
&#x000A0;&#x000A0;&#x000A0;.addProcessor(&#x0201C;FaceMarking&#x0201D;, new
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;PersonFaceMarkingProcessor(), &#x0201C;InputPhotos&#x0201D;,&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x0201C;FaceRecognition&#x0201D;)
&#x000A0;&#x000A0;&#x000A0;.addProcessor(&#x0201C;AlertGenerator&#x0201D;, new
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;AlertGeneratorProcessor(), &#x0201C;FaceRecognition&#x0201D;)
&#x000A0;&#x000A0;&#x000A0;.addSink(&#x0201C;SuspectAlerts&#x0201D;, suspectAlertsSink,
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x0201C;AlertGenerator&#x0201D;)
&#x000A0;&#x000A0;&#x000A0;.addSink(&#x0201C;OutputPhotos&#x0201D;, outputPhotosSink,
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x0201C;FaceMarking&#x0201D;);
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;&#x000A0;
...
</preformat>
</sec>
</sec>
<sec sec-type="conclusions" id="s8">
<title>8. Conclusions</title>
<p>We introduced SPAF, a Stream Processing Abstraction Framework, as an evolution of RAM3S. As common for an abstraction framework, SPAF hides the working details of subsystems conceived for stream processing (like Samza and Storm), allowing reusability, interoperability, flexibility, and extensibility.<xref ref-type="fn" rid="fn0004"><sup>4</sup></xref> We believe that the use of SPAF could effectively ease the development of multimedia stream data mining applications in a distributed scenario. This is clearly helpful to implement an application on top of a stream processing Big Data platform (since the developer can abstract the details specific to the framework) and also to compare performance of different stream processing platforms for a specific application, e.g., for benchmarking (Prakash, <xref ref-type="bibr" rid="B12">2018</xref>). We finally highlight advantages and current limitations of SPAF by providing an analysis of its performance on a series of features (variables) that we believe are important for a software framework: These are described in <xref ref-type="table" rid="T2">Table 2</xref>, where we also provide a comparison with RAM3S, i.e., SPAF predecessor and only competitor. In this way, future versions of SPAF (and also future competitors) could be mapped to this table, highlighting their pros and cons.</p>
<table-wrap position="float" id="T2">
<label>Table 2</label>
<caption><p>Comparison between RAM3S and SPAF (<italic>n</italic> denotes the number of nodes in the topology).</p></caption> 
<table frame="box" rules="all">
<thead>
<tr style="background-color:&#x00023;919498;color:&#x00023;ffffff">
<th valign="top" align="left"><bold>Feature</bold></th>
<th valign="top" align="left"><bold>RAM3S</bold></th>
<th valign="top" align="left"><bold>SPAF</bold></th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top" align="left">Creation of the application</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (boilerplate code, &#x000A7; 3.1)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (boilerplate code, &#x000A7; 4.4)</td>
</tr> <tr>
<td valign="top" align="left">Framework independence</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (SPE-dependent code repeated over applications, &#x000A7; 3.1)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (config file, &#x000A7; 4.4)</td>
</tr> <tr>
<td valign="top" align="left">Connector independence</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (connector-dependent code in the <monospace>Receiver</monospace>, &#x000A7; 3.1)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (config file, &#x000A7; 4.4)</td>
</tr> <tr>
<td valign="top" align="left">Topology shape</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0003.tif"/> (single node topology)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (linear topology, extensible to DAG, &#x000A7; 7)</td>
</tr> <tr>
<td valign="top" align="left">Statefulness of computation</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (single node topology)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (stateless only, &#x000A7; 4.1)</td>
</tr> <tr>
<td valign="top" align="left">Physical topology</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (single node topology)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (extensible, &#x000A7; 7.2)</td>
</tr> <tr>
<td valign="top" align="left">Extension to new SPEs</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0003.tif"/> (need to write code for each app, &#x000A7; 4.4)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (SPE SPI, &#x000A7; 4)</td>
</tr> <tr>
<td valign="top" align="left">Extension to new connectors</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0002.tif"/> (connector-dependent code in the <monospace>Receiver</monospace>, &#x000A7; 3.1)</td>
<td valign="top" align="left" rowspan="2"><inline-graphic xlink:href="fdata-06-1227156-i0001.tif"/> (connector SPI, &#x000A7; 4)</td>
</tr> <tr>
<td valign="top" align="left">Time overhead</td>
<td valign="top" align="left"><italic>O</italic>(1) (single node topology)</td>
<td valign="top" align="left"><italic>O</italic>(<italic>n</italic>) (once, &#x000A7; 6)</td>
</tr>
<tr>
<td valign="top" align="left">Space overhead</td>
<td valign="top" align="left"><italic>O</italic>(1) (single node topology)</td>
<td valign="top" align="left"><italic>O</italic>(<italic>n</italic>) (&#x000A7; 6)</td>
</tr>
</tbody>
</table>
</table-wrap>
</sec>
<sec sec-type="ethics-statement" id="s9">
<title>Ethics statement</title>
<p>Written informed consent was obtained from the individual(s) for the publication of any identifiable images or data included in this article.</p></sec>
<sec sec-type="author-contributions" id="s10">
<title>Author contributions</title>
<p>All authors equally contributed to the conception and design of the study, the writing of the manuscript and its revision. All authors contributed to manuscript revision, read, and approved the submitted version.</p>
</sec>
</body>
<back>
<ack><p>The authors thank Nicol&#x000F2; Scarpa for implementing SPAF and maintaining the github repository. Most of the figures, as well as the analogy between SPAF and Virgil, have been created by Nicol&#x000F2;, and elaborated by the authors.</p>
</ack>
<sec sec-type="COI-statement" id="conf1">
<title>Conflict of interest</title>
<p>The authors declare that the research was conducted in the absence of any commercial or financial relationships that could be construed as a potential conflict of interest.</p>
</sec>
<sec sec-type="disclaimer" id="s11">
<title>Publisher&#x00027;s note</title>
<p>All claims expressed in this article are solely those of the authors and do not necessarily represent those of their affiliated organizations, or those of the publisher, the editors and the reviewers. Any product that may be evaluated in this article, or claim that may be made by its manufacturer, is not guaranteed or endorsed by the publisher.</p>
</sec>
<fn-group>
<fn id="fn0001"><p><sup>1</sup><ext-link ext-link-type="uri" xlink:href="https://news.italy24.press/local/509606.html">https://news.italy24.press/local/509606.html</ext-link></p></fn>
<fn id="fn0002"><p><sup>2</sup>Other applications that have been included in RAM3S (Bartolini and Patella, <xref ref-type="bibr" rid="B4">2021</xref>) are plate detection/recognition (Du et al., <xref ref-type="bibr" rid="B5">2013</xref>) and printed text recognition in videos.</p></fn>
<fn id="fn0003"><p><sup>3</sup>The JMS specification is available at <ext-link ext-link-type="uri" xlink:href="https://javaee.github.io/jms-spec/">https://javaee.github.io/jms-spec/</ext-link>.</p></fn>
<fn id="fn0004"><p><sup>4</sup>Quoting David Wheeler: &#x0201C;All problems in computer science can be solved by another level of indirection&#x0201D; (Spinellis, <xref ref-type="bibr" rid="B14">2007</xref>).</p></fn>
</fn-group>
<ref-list>
<title>References</title>
<ref id="B1">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Alexandrov</surname> <given-names>A.</given-names></name> <name><surname>Bergmann</surname> <given-names>R.</given-names></name> <name><surname>Ewen</surname> <given-names>S.</given-names></name> <name><surname>Freytag</surname> <given-names>J.-C.</given-names></name> <name><surname>Hueske</surname> <given-names>F.</given-names></name> <name><surname>Heise</surname> <given-names>A.</given-names></name> <etal/></person-group>. (<year>2014</year>). <article-title>The Stratosphere platform for big data analytics</article-title>. <source>VLDB J</source>. <volume>23</volume>, <fpage>939</fpage>&#x02013;<lpage>964</lpage>. <pub-id pub-id-type="doi">10.1007/s00778-014-0357-y</pub-id></citation>
</ref>
<ref id="B2">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Bartolini</surname> <given-names>I.</given-names></name> <name><surname>Patella</surname> <given-names>M.</given-names></name></person-group> (<year>2018</year>). <article-title>A general framework for real-time analysis of massive multimedia streams</article-title>. <source>Multim. Syst</source>. <volume>24</volume>, <fpage>391</fpage>&#x02013;<lpage>406</lpage>. <pub-id pub-id-type="doi">10.1007/s00530-017-0566-5</pub-id></citation>
</ref>
<ref id="B3">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Bartolini</surname> <given-names>I.</given-names></name> <name><surname>Patella</surname> <given-names>M.</given-names></name></person-group> (<year>2019</year>). <article-title>Real-time stream processing in social networks with RAM3S</article-title>. <source>Future Internet</source> <volume>11</volume>, <fpage>249</fpage>. <pub-id pub-id-type="doi">10.3390/fi11120249</pub-id></citation>
</ref>
<ref id="B4">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Bartolini</surname> <given-names>I.</given-names></name> <name><surname>Patella</surname> <given-names>M.</given-names></name></person-group> (<year>2021</year>). <article-title>The metamorphosis (of RAM3S)</article-title>. <source>Appl. Sci</source>. 11, 1158. <pub-id pub-id-type="doi">10.3390/app112411584</pub-id></citation>
</ref>
<ref id="B5">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Du</surname> <given-names>S.</given-names></name> <name><surname>Ibrahim</surname> <given-names>M.</given-names></name> <name><surname>Shehata</surname> <given-names>M.</given-names></name> <name><surname>Badawy</surname> <given-names>W.</given-names></name></person-group> (<year>2013</year>). <article-title>Automatic license plate recognition (alpr): A state-of-the-art review</article-title>. <source>IEEE Trans. Circ. Syst. Video Technol</source>. <volume>23</volume>, <fpage>311</fpage>&#x02013;<lpage>325</lpage>. <pub-id pub-id-type="doi">10.1109/TCSVT.2012.2203741</pub-id></citation>
</ref>
<ref id="B6">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Gamma</surname> <given-names>E.</given-names></name> <name><surname>Helm</surname> <given-names>R.</given-names></name> <name><surname>Johnson</surname> <given-names>R.</given-names></name> <name><surname>Vlissides</surname> <given-names>J.</given-names></name></person-group> (<year>1995</year>). <source>Design Patterns: Elements of Reusable Object-Oriented Software</source>. <publisher-loc>Boston, MA, USA</publisher-loc>: <publisher-name>Addison-Wesley Longman Publishing Co., Inc.</publisher-name></citation>
</ref>
<ref id="B7">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>&#x00141;opatka</surname> <given-names>K.</given-names></name> <name><surname>Kotus</surname> <given-names>J.</given-names></name> <name><surname>Czy&#x0017C;ewski</surname> <given-names>A.</given-names></name></person-group> (<year>2016</year>). <article-title>Detection, classification and localization of acoustic events in the presence of background noise for acoustic surveillance of hazardous situations</article-title>. <source>Multim. Tools Applic</source>. <volume>75</volume>, <fpage>10407</fpage>&#x02013;<lpage>10439</lpage>. <pub-id pub-id-type="doi">10.1007/s11042-015-3105-4</pub-id></citation>
</ref>
<ref id="B8">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Mu</surname> <given-names>C.</given-names></name> <name><surname>Xie</surname> <given-names>J.</given-names></name> <name><surname>Yan</surname> <given-names>W.</given-names></name> <name><surname>Liu</surname> <given-names>T.</given-names></name> <name><surname>Li</surname> <given-names>P.</given-names></name></person-group> (<year>2016</year>). <article-title>A fast recognition algorithm for suspicious behavior in high definition videos</article-title>. <source>Multim. Syst</source>. <volume>22</volume>, <fpage>275</fpage>&#x02013;<lpage>285</lpage>. <pub-id pub-id-type="doi">10.1007/s00530-015-0456-7</pub-id></citation>
</ref>
<ref id="B9">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Noghabi</surname> <given-names>S. A.</given-names></name> <name><surname>Paramasivam</surname> <given-names>K.</given-names></name> <name><surname>Pan</surname> <given-names>Y.</given-names></name> <name><surname>Ramesh</surname> <given-names>N.</given-names></name> <name><surname>Bringhurst</surname> <given-names>J.</given-names></name> <name><surname>Gupta</surname> <given-names>I.</given-names></name> <etal/></person-group>. (<year>2017</year>). <article-title>Samza: Stateful scalable stream processing at LinkedIn</article-title>. <source>Proc. VLDB Endowment</source> <volume>10</volume>, <fpage>1634</fpage>&#x02013;<lpage>1645</lpage>. <pub-id pub-id-type="doi">10.14778/3137765.3137770</pub-id></citation>
</ref>
<ref id="B10">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Persia</surname> <given-names>F.</given-names></name> <name><surname>Bettini</surname> <given-names>F.</given-names></name> <name><surname>Helmer</surname> <given-names>S.</given-names></name></person-group> (<year>2017</year>). <article-title>&#x0201C;An interactive framework for video surveillance event detection and modeling,&#x0201D;</article-title> in <source>Proceedings of the 2017 ACM on onference on Information and Knowledge Management, CIKM 2017</source> (<publisher-loc>New York, NY, USA</publisher-loc>: <publisher-name>Association for Computing Machinery</publisher-name>), <fpage>2515</fpage>&#x02013;<lpage>2518</lpage>. <pub-id pub-id-type="doi">10.1145/3132847.3133164</pub-id></citation>
</ref>
<ref id="B11">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Piatov</surname> <given-names>D.</given-names></name> <name><surname>Helmer</surname> <given-names>S.</given-names></name> <name><surname>Dign&#x000F6;s</surname> <given-names>A.</given-names></name> <name><surname>Persia</surname> <given-names>F.</given-names></name></person-group> (<year>2021</year>). <article-title>Cache-efficient sweeping-based interval joins for extended allen relation predicates</article-title>. <source>VLDB J</source>. <volume>30</volume>, <fpage>379</fpage>&#x02013;<lpage>402</lpage>. <pub-id pub-id-type="doi">10.1007/s00778-020-00650-5</pub-id></citation>
</ref>
<ref id="B12">
<citation citation-type="web"><person-group person-group-type="author"><collab>Prakash</collab></person-group> (<year>2018</year>). <source>Spark Streaming vs. Flink vs Storm vs. Kafka Streams vs. Samza: Choose your stream processing framework</source>. Available online at: <ext-link ext-link-type="uri" xlink:href="https://medium.com/&#x00040;chandanbaranwal/spark-streaming-vs-flink-vs-storm-vs-kafka-streams-vs-samza-choose-your-stream-processing-91ea3f04675b">https://medium.com/&#x00040;chandanbaranwal/spark-streaming-vs-flink-vs-storm-vs-kafka-streams-vs-samza-choose-your-stream-processing-91ea3f04675b</ext-link>. (accessed May 22, 2023).</citation>
</ref>
<ref id="B13">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Roh</surname> <given-names>M.</given-names></name> <name><surname>Lee</surname> <given-names>S.</given-names></name></person-group> (<year>2015</year>). <article-title>Human gesture recognition using a simplified dynamic bayesian network</article-title>. <source>Multim. Syst</source>. <volume>21</volume>, <fpage>557</fpage>&#x02013;<lpage>568</lpage>. <pub-id pub-id-type="doi">10.1007/s00530-014-0414-9</pub-id></citation>
</ref>
<ref id="B14">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Spinellis</surname> <given-names>D.</given-names></name></person-group> (<year>2007</year>). <article-title>&#x0201C;Another level of indirection,&#x0201D;</article-title> in <source>Beautiful Code: Leading Programmers Explain How They Think, chapter 17</source>, eds. A. Oram, and G. Wilson (<publisher-loc>Sebastopol, CA, USA</publisher-loc>: <publisher-name>O&#x00027;Reilly and Associates</publisher-name>), <fpage>279</fpage>&#x02013;<lpage>291</lpage>.</citation>
</ref>
<ref id="B15">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Tang</surname> <given-names>M.</given-names></name> <name><surname>Pongpaichet</surname> <given-names>S.</given-names></name> <name><surname>Jain</surname> <given-names>R.</given-names></name></person-group> (<year>2016</year>). <article-title>&#x0201C;Research challenges in developing multimedia systems for managing emergency situations,&#x0201D;</article-title> in <source>Proceedings of the 24th ACM International Conference on Multimedia, MM &#x00027;16</source> (<publisher-loc>New York, NY, USA</publisher-loc>: <publisher-name>Association for Computing Machinery</publisher-name>), <fpage>938</fpage>&#x02013;<lpage>947</lpage>. <pub-id pub-id-type="doi">10.1145/2964284.2976761</pub-id></citation>
</ref>
<ref id="B16">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Turk</surname> <given-names>M. A.</given-names></name> <name><surname>Pentland</surname> <given-names>A.</given-names></name></person-group> (<year>1991</year>). <article-title>&#x0201C;Face recognition using eigenfaces,&#x0201D;</article-title> in <source>IEEE Computer Society Conference on Computer Vision and Pattern Recognition, CVPR 1991</source> (<publisher-loc>IEEE</publisher-loc>), <fpage>586</fpage>&#x02013;<lpage>591</lpage>.</citation>
</ref>
<ref id="B17">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Viola</surname> <given-names>P.</given-names></name> <name><surname>Jones</surname> <given-names>M.</given-names></name></person-group> (<year>2001</year>). <article-title>&#x0201C;Rapid object detection using a boosted cascade of simple features,&#x0201D;</article-title> in <source>Proceedings of the 2001 IEEE Computer Society Conference on Computer Vision and Pattern Recognition. CVPR 2001</source> (<publisher-loc>Los Alamitos, CA, USA</publisher-loc>: <publisher-name>IEEE Computer Society</publisher-name>), <fpage>511</fpage>.</citation>
</ref>
<ref id="B18">
<citation citation-type="book"><person-group person-group-type="author"><name><surname>Zaharia</surname> <given-names>M.</given-names></name> <name><surname>Chowdhury</surname> <given-names>M.</given-names></name> <name><surname>Franklin</surname> <given-names>M. J.</given-names></name> <name><surname>Shenker</surname> <given-names>S.</given-names></name> <name><surname>Stoica</surname> <given-names>I.</given-names></name></person-group> (<year>2010</year>). <article-title>&#x0201C;Spark: Cluster computing with working sets,&#x0201D;</article-title> in <source>Proceedings of the 2nd USENIX Conference on Hot Topics in Cloud Computing, HotCloud&#x00027;10</source> (<publisher-loc>New York, NY</publisher-loc>: <publisher-name>USA: USENIX Association</publisher-name>), <fpage>10</fpage>.</citation>
</ref>
<ref id="B19">
<citation citation-type="journal"><person-group person-group-type="author"><name><surname>Zhang</surname> <given-names>J.</given-names></name> <name><surname>Han</surname> <given-names>Y.</given-names></name> <name><surname>Jiang</surname> <given-names>J.</given-names></name></person-group> (<year>2016</year>). <article-title>Tucker decomposition-based tensor learning for human action recognition</article-title>. <source>Multim. Syst</source>. <volume>22</volume>, <fpage>343</fpage>&#x02013;<lpage>353</lpage>. <pub-id pub-id-type="doi">10.1007/s00530-015-0464-7</pub-id></citation>
</ref>
</ref-list>
</back>
</article>