Management Options
==================

.. _management:

.. contents:: Table of Contents

SPBench allows users to manage the input stream, workload behavior, and other options in some ways. Some characteristics, such as data input frequency and batching, can be tuned statically or dynamically during the execution of a benchmark.

General Management
------------------

Here we present some general management options. These options can be statically set using specific arguments in the command-line through the ``exec`` command. See :doc:`CLI` or run ``./SPBench exec -h`` for more information.

All of these are also OPTIONAL arguments that you can use within the 'exec' command.

- ``-in-memory``

    It runs the application in-memory, which means that all the input is first loaded into the memory before start processing it. The opposite is true for the writing phase, where the result stays in memory and is only writen to the disk after all the input is proccessed.

- ``-nthreads <number_of_threads>``

    It defines a number of threads to run the parallel benchmark available within SPBench. To be more precise, the degree of parallelism of the parallel stages (Obs.: some PPIs can create more threads than parallel stages). It shows up as a global variable that can be used inside the parallel benchmarks, so users can also use this variable to set the parallelism in their custom benchmarks.

- ``-user-arg``
 
    Allow users to use custom arguments. Arguments that users pass on the command line via this option can be retrieved inside the benchmark code via the ``spb::SPBench::getArg(<argument_index>)`` method.

- ``-d``

   This a specific argument for bzip2 benchmarks. You can use it to run this application in decompress mode. Observe that for de decompression mode it is required a compressed file as input (e.g. my_compressed_file.tar.bz2). The compressed input classes are registered with a '_d' at the end (e.g. small_d, large_d, etc.).


Batching Management
-------------------

There are some ways of changing the size of batches in SPBench. The first way is to set fixed-size batches at the beginning of the execution by adding some arguments to the exec command.

- ``-batch <batch_size>``

   Change the size of the batches based on a fixed number of items. By default, the size of each batch is 1. If used with ``-batch-interval``, the batch size will be set according to whichever occurs first.

- ``-batch-interval <time_interval_sec>``

   Change the size of the batches based on a given time period (seconds). By default, the time period is 0, which means it is disabled. If used with ``-batch``, the batch size will be set according to whichever occurs first.

There are some methods of the SPbench class that users can use to dynamically access or modify the batch sizes
It can be done either inside or outside the stream region of the benchmarks. 
Users can use the following SPBench methods for that: 

- ``spb::SPBench::setBatchSize(<batch_size>)``.

or

- ``spb::SPBench::setBatchInterval(<time_interval_sec>)``

Usage example:

.. code-block:: C++

    // Example of possible use for custom user argument
    my_PPI.setQueueSize(spb::SPBench::getArg(0));
    
    /* Stream region */
    while(1){
        spb::Item item;
        if(!spb::Source::op(item)) break;
        if(/*my_condition*/){
            /* Increment the current batch size by 1 */
            spb::SPBench::setBatchSize(spb::SPBench::getBatchSize()+1);
        }
        spb::Some::op(item);
        spb::Some_other::op(item);
        spb::Sink::op(item);
    } // End of stream region

Frequency Management
--------------------

Frequency in SPBench means the number of items avaliable for the sources per second.
Of course, there is a maximum frequency for each application, which is limited by the speed at which the items are read from the input stream. In normal executions this speed is limited by the time it takes to read the data from the disk. Therefore, to achieve high frequencies it is recommended to run the benchmark using the in-memory option, since reading data from memory is usually faster than reading from disk.

The way to manage the data input frequency in SPBench is similar to the way we manage the batching. Users can change the frequency once at the beginning of the execution or they can also change it dynamically during the execution of the benchmark.

To change it statically, users can add the following arguments in the **exec** command:

- ``-frequency <items_per_second>``

    Set a frequency for items to be available for the source operator. By default, there is no limit, which means that the default frequency is the one given by the speed of reading items from the disk (or from the memory, in a in-memory execution). The frequency control in SPBench is done by adding a varying time-delay for each item generation. So higher time-delays imply in lower frequencies.

- ``-freq-pattern <frequency_pattern>`` (pattern,period,max,min). 

    This argument overwrites the -frequency command and sets a varying frequency for the input stream. Users can select and set a frequency variation pattern. For this argument users need to supply a tuple string: <pattern,period,max,min>, where pattern can be "wave", "spike", "binary", "increasing" or "decreasing". Period is the duration in seconds of one cycle of the pattern. And min is the minimum frequency and max the maximum frequency, defined in items per second. For the spike pattern users can also set the duration of the spikes as percentage of the period (0-100) (e.g. <pattern,period,max,min,spike>). The default spike duration is 10 percent of the period. Usage example: ``-freq-pattern wave,10,5,80``

These two frequency management options can also be changed at anytime during the execution by using the methods below:

- ``spb::SPBench::setFrequency(<items_per_second>)`` 

Set a frequency for items to be available for the source operator (same as the ``-frequency`` argumment).

- ``spb::SPBench::setFrequencyPattern(<frequency_pattern>)``

This SPBench method allows users to set and change a frequency pattern at anytime during a benchmark's execution.

Usage example:

.. code-block:: C++

    // Example of frequency pattern usage
    spb::SPBench::setFrequencyPattern("wave", 12, 5.3, 70);
    
    /* Stream region */
    while(1){
        spb::Item item;
        if(!spb::Source::op(item)) break;
        if(/*my_condition*/){           
            /* Decrement the current frequency by 5 */
            spb::SPBench::setFrequency(spb::SPBench::getFrequency()-5); // 100 items per second
        }
        spb::Some::op(item);
        spb::Some_other::op(item);
        spb::Sink::op(item);
    } // End of stream region

Management Options for Multi-source Benchmarks
----------------------------------------------

In multi-source benchmarks, each source offers to users some methods to control its behavior individually.

   - ``source.setBatchSize(items_per_batch)``
      
      This method can be used to change the batch size of the items on the stream.

   - ``source.setBatchInterval(batch_interval_in_sec)``
      
      This method can be used to change the batch time interval of the stream.

   - ``source.setFrequency(items_per_second)``
      
      If the in-memory option was not enable in the execution command, the maximum frequency will be limited by the speed of the disk.
      Ideally, this option may be used in an in-memory execution to achieve high speed data.

   - ``source.setQueueMaxSize(queue_size);``
      
      This option changes the queue size for te respective source. It has no impact on the inter-stage queues of the parallel implementations.

   - ``source.init()``
      
      It is necessary to run this method once before the stream region to start the source execution.

   Alternativelly, these attributes can be specified through the constructor of the source object:

   - ``spb::Source source(<batch_size>, <batch_interval>, <queue_size>, <frequency>);``

   When using this second method, ``source.init()`` is not required.

Code example:

.. code-block:: C++

    ...
   	// Compact source creation method. This source will run immediately.
	// Parameters: <batch_size>, <batch_interval>, <queue_size>, <frequency>
	spb::Source source1(2, 0, 1, 0);

    // Alternative source creation method
	spb::Source source2;

	// These parameters can be changed anytime during execution
	source2.setBatchSize(1); // 1 item per batch
	source2.setBatchInterval(0.5); // 500 ms batch window
	source2.setQueueMaxSize(3); // 3 slots in this source's queue
	source2.setFrequency(30); // 30 items per second
	
	// You must use the init() method to run the source2
    // because it dos not run immediately on creation
	source2.init();

	/* Stream region */
	while(!(source1.depleted() && source2.depleted())){
        ...
        if(/*my condition*/){
            // all parameters can be changed anytime
            source1.setQueueMaxSize(4);
            source2.setFrequency(50);
        }
        ...
	}
    ...

