Appendix: Result File Formats

Native Result Files

The file format described here applies to both output vector and output scalar files. Their formats are consistent, only the types of entries occurring in them are different. This unified format also means that they can be read with a common routine.

Result files are line oriented. A line consists of one or more tokens, separated by whitespace. Tokens either do not contain whitespace, or whitespace is escaped using a backslash, or are quoted using double quotes. Escaping within quotes using backslashes is also permitted.

The first token of a line usually identifies the type of the entry. A notable exception is an output vector data line, which begins with a numeric identifier of the given output vector.

A line starting with # as the first non-whitespace character denotes a comment, and is to be ignored during processing.

Result files are written from simulation runs. A simulation run generates physically contiguous sets of lines into one or more result files. (That is, lines from different runs do not arbitrarily mix in the files.)

A run is identified by a unique textual runId, which appears in all result files written during that run. The runId may appear on the user interface, so it should be somewhat meaningful to the user. Nothing should be assumed about the particular format of runId, but it will be some string concatenated from the simulated network’s name, the time/date, the hostname, and other pieces of data to make it unique.

A simulation run will typically write into two result files (.vec and .sca). However, when using parallel distributed simulation, the user will end up with several .vec and .sca files, because different partitions (a separate process each) will write into different files. However, all these files will contain the same runId, so it is possible to relate data that belong together.

Entry types are:

  • version: result file version

  • run: simulation run identifier

  • attr: run, vector, scalar or statistics object attribute

  • itervar: iteration variable

  • config: configuration entry

  • par: module parameter

  • scalar: scalar data

  • vector: vector declaration

  • vector-id: vector data

  • file: vector file attributes

  • statistic: statistics object

  • field: field of a statistics object

  • bin: histogram bin

Version

Specifies the format of the result file. It is written at the beginning of the file.

Syntax:

version versionNumber

The version described in this document is 3, used since OMNeT++ 6.0. Version 1 files were produced by OMNeT++ 3.x and earlier, and version 2 files by OMNeT++ 4.x and 5.x. [1]

Run Declaration

Marks the beginning of a new run in the file. Entries after this line belong to this run.

Syntax:

run runId

Example:

run TokenRing1-0-20080514-18:19:44-3248

Typically there will be one run per file, but this is not mandatory. In cases when there are more than one run in a file and it is not feasible to keep the entire file in memory during analysis, the offsets of the run lines may be indexed for more efficient random access.

The run line may be immediately followed by attribute lines. Attributes may store generic data like the network name, date/time of running the simulation, configuration options that took effect for the simulation, etc.

Run attribute names used by OMNeT++ include the following:

Generic attribute names:

  • network: name of the network simulated

  • datetime: date/time associated with the run

  • processid: the PID of the simulation process

  • inifile: the main configuration file

  • configname: name of the inifile configuration

  • seedset: index of the seed-set use for the simulation

Attributes associated with parameter studies (iterated runs):

  • runnumber: the run number within the parameter study

  • experiment: experiment label

  • measurement: measurement label

  • replication: replication label

  • repetition: the loop counter for repetitions with different seeds

  • iterationvars: string containing the values of the iteration variables

  • iterationvarsf: like iterationvars, but sanitized for use as part of file names

An example run header:

run PureAlohaExperiment-0-20200304-18:05:49-194559
attr configname PureAlohaExperiment
attr datetime 20200304-18:05:49
attr experiment PureAlohaExperiment
attr inifile omnetpp.ini
attr iterationvars "$numHosts=10, $iaMean=1"
attr measurement "$numHosts=10, $iaMean=1"
attr network Aloha
attr processid 194559
attr repetition 0
attr replication #0
attr resultdir results
attr runnumber 0
attr seedset 0
itervar iaMean 1
itervar numHosts 10
config repeat 2
config sim-time-limit 90min
config network Aloha
config Aloha.numHosts 10
config Aloha.host[*].iaTime exponential(1s)
config Aloha.numHosts 20
config Aloha.txRate 9.6kbps
config **.x "uniform(0m, 1000m)"
config **.y "uniform(0m, 1000m)"
config **.idleAnimationSpeed 1

Attributes

Contains an attribute for the preceding run, vector, scalar or statistics object. Attributes can be used for saving arbitrary extra information for objects; processors should ignore unrecognized attributes.

Syntax:

attr name value

Example:

attr network "largeNet"

Iteration Variables

Contains an iteration variable for the given run.

Syntax:

itervar name value

Examples:

itervar numHosts 10
itervar tcpType Reno

Configuration Entries

The configuration of the simulation is captured in the result file as an ordered list of config lines. The list contains both the contents of ini files and the options given one the command line.

The order of lines represents a flattened view of the ini file(s). The contents of sections are recorded in an order that reflects the section inheritance graph: derived sections precede the sections they extend (so General comes last), and the contents of unrelated sections are omitted. Command like options are at the top. The relative order of lines within ini file sections are preserved. This order corresponds to the search order of entries that contain wildcards (i.e. first match wins).

Values are saved verbatim, except that iteration variables are substituted in them.

Syntax:

config key value

Example config lines:

config sim-time-limit 90min
config network Aloha
config Aloha.numHosts 10
config Aloha.host[*].iaTime exponential(1s)
config **.x "uniform(0m, 1000m)"

Scalar Data

Contains an output scalar value.

Syntax:

scalar moduleName scalarName value

Examples:

scalar "net.switchA.relay" "processed frames" 100

Scalar lines may be immediately followed by attribute lines. OMNeT++ uses the following attributes for scalars:

  • title: suggested title on charts

  • unit: measurement unit, e.g. s for seconds

Vector Declaration

Defines an output vector.

Syntax:

vector vectorId moduleName vectorName

vector vectorId moduleName vectorName columnSpec

Where columnSpec is a string, encoding the meaning and ordering the columns of data lines. Characters of the string mean:

  • E event number

  • T simulation time

  • V vector value

Common values are TV and ETV. The default value is TV.

Vector lines may be immediately followed by attribute lines. OMNeT++ uses the following attributes for vectors:

  • title: suggested vector title on charts

  • unit: measurement unit, e.g. s for seconds

  • enum: symbolic names for values of the vector; syntax is "IDLE=0, BUSY=1, OFF=2"

  • type: data type, one of int, double and enum

  • interpolationmode: hint for interpolation mode on the chart: none (=do not connect the dots), sample-hold, backward-sample-hold, linear

  • min: minimum value

  • max: maximum value

Vector Data

Adds a value to an output vector. This is the same as in older output vector files.

Syntax:

vectorId column1 column2 …

Simulation times and event numbers within an output vector are required to be in increasing order.

Performance note: Data lines belonging to the same output vector may be written out in clusters (of size roughly a multiple of the disk’s physical block size). Then, since an output vector file is typically not kept in memory during analysis, indexing the start offsets of these clusters allows one to read the file and seek in it more efficiently. This does not require any change or extension to the file format.

Index Header

The first line of the index file stores the size and modification date of the vector file. If the attributes of a vector file differ from the information stored in the index file, then the IDE automatically rebuilds the index file.

Syntax:

file filesize modificationDate

Index Data

Stores the location and statistics of blocks in the vector file.

Syntax:

vectorId offset length firstEventNo lastEventNo firstSimtime lastSimtime count min max sum sqrsum

where

  • offset: the start offset of the block

  • length: the length of the block

  • firstEventNo, lastEventNo: the event number range of the block (optional)

  • firstSimtime, lastSimtime: the simtime range of the block

  • count, min, max, sum, sqrsum: collected statistics of the values in the block

Statistics Object

Represents a statistics object.

Syntax:

statistic moduleName statisticName

Example:

statistic Aloha.server  "collision multiplicity"

A statistic line may be followed by field and attribute lines, and a series of bin lines that represent histogram data.

OMNeT++ uses the following attributes:

  • title: suggested title on charts

  • unit: measurement unit, e.g. s for seconds

  • type: type of the collected values: int or double; the default is double

A full example with fields, attributes and histogram bins:

statistic Aloha.server  "collision multiplicity"
field count 13908
field mean 6.8510209951107
field stddev 5.2385484477843
field sum 95284
field sqrsum 1034434
field min 2
field max 65
attr type int
attr unit packets
bin -INF    0
bin 0   0
bin 1   0
bin 2   2254
bin 3   2047
bin 4   1586
bin 5   1428
bin 6   1101
bin 7   952
bin 8   785
...
bin 52  2

Field

Represents a field in a statistics object.

Syntax:

field fieldName value

Example:

field sum 95284

Fields:

  • count: observation count

  • mean: mean of the observations

  • stddev: standard deviation

  • min: minimum of the observations

  • max: maximum of the observations

  • sum: sum of the observations

  • sqrsum: sum of the squared observations

For weighted statistics, sum and sqrsum are replaced by the following fields:

  • weights: sum of the weights

  • weightedSum: the weighted sum of the observations

  • sqrSumWeights: sum of the squared weights

  • weightedSqrSum: weighted sum of the squared observations

Histogram Bin

Represents a bin in a histogram object.

Syntax:

bin binLowerBound value

Histogram name and module is defined on the statistic line, which is followed by several bin lines to contain data. Any non-bin line marks the end of the histogram data.

The binLowerBound column of bin lines represent the (inclusive) lower bound of the given histogram cell. Bin lines are in increasing binLowerBound order.

The value column of a bin line represents the observation count in the given cell: value k is the number of observations greater or equal to binLowerBound k, but smaller than binLowerBound k+1. Value is not necessarily an integer, because the cKSplit and cPSquare algorithms produce non-integer estimates. The first bin line is the underflow cell, and the last bin line is the overflow cell.

Example:

bin -INF  0
bin 0 4
bin 2 6
bin 4 2
bin 6 1

SQLite Result Files

The database structure in SQLite result files is created with the following SQL statements. Scalar and vector files are identical in structure, they only differ in data.

CREATE TABLE run
(
    runId       INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    runName     TEXT NOT NULL,
    simtimeExp  INTEGER NOT NULL
);

CREATE TABLE runAttr
(
    runId       INTEGER  NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    attrName    TEXT NOT NULL,
    attrValue   TEXT NOT NULL
);

CREATE TABLE runItervar
(
    runId       INTEGER  NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    itervarName TEXT NOT NULL,
    itervarValue TEXT NOT NULL
);

CREATE TABLE runConfig
(
    runId       INTEGER NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    configKey   TEXT NOT NULL,
    configValue TEXT NOT NULL,
    configOrder INTEGER NOT NULL
);

CREATE TABLE scalar
(
    scalarId      INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    runId         INTEGER  NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    moduleName    TEXT NOT NULL,
    scalarName    TEXT NOT NULL,
    scalarValue   REAL        -- cannot be NOT NULL, because sqlite converts NaN double value to NULL
);

CREATE TABLE scalarAttr
(
    scalarId      INTEGER  NOT NULL REFERENCES scalar(scalarId) ON DELETE CASCADE,
    attrName      TEXT NOT NULL,
    attrValue     TEXT NOT NULL
);

CREATE TABLE parameter
(
    paramId       INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    runId         INTEGER  NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    moduleName    TEXT NOT NULL,
    paramName     TEXT NOT NULL,
    paramValue    TEXT NOT NULL
);

CREATE TABLE paramAttr
(
    paramId       INTEGER  NOT NULL REFERENCES parameter(paramId) ON DELETE CASCADE,
    attrName      TEXT NOT NULL,
    attrValue     TEXT NOT NULL
);

CREATE TABLE statistic
(
    statId        INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    runId         INTEGER NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    moduleName    TEXT NOT NULL,
    statName      TEXT NOT NULL,
    isHistogram   INTEGER NOT NULL,   -- actually, BOOL
    isWeighted    INTEGER NOT NULL,   -- actually, BOOL
    statCount     INTEGER NOT NULL,
    statMean      REAL,   -- note: computed; stored for convenience
    statStddev    REAL,   -- note: computed; stored for convenience
    statSum       REAL,
    statSqrsum    REAL,
    statMin       REAL,
    statMax       REAL,
    statWeights          REAL,  -- note: names of this and subsequent fields are consistent with textual sca file field names
    statWeightedSum      REAL,
    statSqrSumWeights    REAL,
    statWeightedSqrSum   REAL
);

CREATE TABLE statisticAttr
(
    statId        INTEGER NOT NULL REFERENCES statistic(statId) ON DELETE CASCADE,
    attrName      TEXT NOT NULL,
    attrValue     TEXT NOT NULL
);

CREATE TABLE histogramBin
(
    statId        INTEGER NOT NULL REFERENCES statistic(statId) ON DELETE CASCADE,
    lowerEdge     REAL NOT NULL,
    binValue      REAL NOT NULL
);

CREATE TABLE vector
(
    vectorId        INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    runId           INTEGER NOT NULL REFERENCES run(runId) ON DELETE CASCADE,
    moduleName      TEXT NOT NULL,
    vectorName      TEXT NOT NULL,
    vectorCount     INTEGER,    -- cannot be NOT NULL because we fill it in later
    vectorMin       REAL,
    vectorMax       REAL,
    vectorSum       REAL,
    vectorSumSqr    REAL,
    startEventNum   INTEGER,
    endEventNum     INTEGER,
    startSimtimeRaw INTEGER,
    endSimtimeRaw   INTEGER

);

CREATE TABLE vectorAttr
(
    vectorId      INTEGER  NOT NULL REFERENCES vector(vectorId) ON DELETE CASCADE,
    attrName      TEXT NOT NULL,
    attrValue     TEXT NOT NULL
);

CREATE TABLE vectorData
(
    vectorId      INTEGER NOT NULL REFERENCES vector(vectorId) ON DELETE CASCADE,
    eventNumber   INTEGER NOT NULL,
    simtimeRaw    INTEGER NOT NULL,
    value         REAL  -- cannot be NOT NULL because of NaN values
);

Notes:

  1. To preserve precision, simulation time is stored in raw form, i.e. the underlying int64 is stored as an integer. To get the real value, they have to be multiplied by 10 to the power of the simtime exponent, which is global for the simulation run. The simtime exponent is stored in the simtimeExp column of the run table.

  2. Some columns like vector statistics are not marked as NOT NULL, because of technical reasons: their values are not available at the time of the insertion, only at the end of the simulation.

  3. REAL columns are not marked as NOT NULL, because SQLite stores floating-point NaN values as NULLs.

Caution

SQLite support in OMNeT++ is currently experimental, so the above database structure may change in future releases.