Bug #645: fixes for opening stats file with OMNeT++

This commit is contained in:
Andras Varga
2009-11-11 12:44:09 +01:00
parent 6a54bf77c4
commit 49d1be220f
11 changed files with 244 additions and 49 deletions

View File

@@ -14,3 +14,23 @@ More information on the statistics package and this example is
available online on the ns-3 wiki at:
http://www.nsnam.org/wiki/index.php/Statistical_Framework_for_Network_Simulation
*** Using ns-3 with the OMNeT++ analysis tool ***
The stat framework can write out the result in a format that is compatible with the
output format of OMNeT++ 4 Discrete Event Simulator Framework.
Use the wifi-example-omnet.sh script to generate the results in OMNeT++ format.
If you want to analyse the results with OMNeT++'s result analyser tool:
a) Download OMNeT++ 4 and install it. Start the IDE. (www.omnetpp.org)
b) If you do not want to install the whole simulator framework, there is a seperate
package which contains only the analysis tool from the OMNeT++ package.
You can download it from http://omnetpp.org/download/release/omnetpp-scave.tgz
Once you are running the OMNeT++ IDE or the separate analysis tool (SCAVE)
- Choose File|Import...|Existing Projects into Workspace, then click [Next]
- Select root directory. (choose the examples/stats directory) and click [Finish]
Double click the wifi-example-omnet.anf in the opened project and select
the Chart page to see the created chart. Experiment with the analysis tool and read its
documentation: http://omnetpp.org/doc/omnetpp40/userguide/ch09.html

View File

@@ -200,6 +200,7 @@ int main(int argc, char *argv[]) {
Ptr<CounterCalculator<uint32_t> > totalTx =
CreateObject<CounterCalculator<uint32_t> >();
totalTx->SetKey("wifi-tx-frames");
totalTx->SetContext("node[0]");
Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
MakeBoundCallback(&TxCallback, totalTx));
data.AddDataCalculator(totalTx);
@@ -211,6 +212,7 @@ int main(int argc, char *argv[]) {
Ptr<PacketCounterCalculator> totalRx =
CreateObject<PacketCounterCalculator>();
totalRx->SetKey("wifi-rx-frames");
totalRx->SetContext("node[1]");
Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
MakeCallback(&PacketCounterCalculator::PacketUpdate,
totalRx));
@@ -225,6 +227,7 @@ int main(int argc, char *argv[]) {
Ptr<PacketCounterCalculator> appTx =
CreateObject<PacketCounterCalculator>();
appTx->SetKey("sender-tx-packets");
appTx->SetContext("node[0]");
Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
MakeCallback(&PacketCounterCalculator::PacketUpdate,
appTx));
@@ -237,6 +240,7 @@ int main(int argc, char *argv[]) {
Ptr<CounterCalculator<> > appRx =
CreateObject<CounterCalculator<> >();
appRx->SetKey("receiver-rx-packets");
appRx->SetContext("node[1]");
receiver->SetCounter(appRx);
data.AddDataCalculator(appRx);
@@ -263,6 +267,7 @@ int main(int argc, char *argv[]) {
Ptr<PacketSizeMinMaxAvgTotalCalculator> appTxPkts =
CreateObject<PacketSizeMinMaxAvgTotalCalculator>();
appTxPkts->SetKey("tx-pkt-size");
appTxPkts->SetContext("node[0]");
Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
MakeCallback
(&PacketSizeMinMaxAvgTotalCalculator::PacketUpdate,
@@ -277,6 +282,7 @@ int main(int argc, char *argv[]) {
Ptr<TimeMinMaxAvgTotalCalculator> delayStat =
CreateObject<TimeMinMaxAvgTotalCalculator>();
delayStat->SetKey("delay");
delayStat->SetContext(".");
receiver->SetDelayTracker(delayStat);
data.AddDataCalculator(delayStat);

View File

@@ -29,7 +29,8 @@ namespace ns3 {
//------------------------------------------------------------
//--------------------------------------------
template <typename T = uint32_t>
class MinMaxAvgTotalCalculator : public DataCalculator {
class MinMaxAvgTotalCalculator : public DataCalculator,
public StatisticalSummary {
public:
MinMaxAvgTotalCalculator();
virtual ~MinMaxAvgTotalCalculator();
@@ -38,6 +39,15 @@ namespace ns3 {
virtual void Output(DataOutputCallback &callback) const;
long getCount() const { return m_count; }
double getSum() const { return m_total; }
double getMin() const { return m_min; }
double getMax() const { return m_max; }
double getMean() const { return m_total / (double)m_count; }
double getStddev() const { return NaN; } // unsupported
double getVariance() const { return NaN; } // unsupported
double getSqrSum() const { return NaN; } // unsupported
protected:
virtual void DoDispose(void);
@@ -86,23 +96,15 @@ namespace ns3 {
}
// end MinMaxAvgTotalCalculator::Update
}
template <typename T>
void
MinMaxAvgTotalCalculator<T>::Output(DataOutputCallback &callback) const
{
callback.OutputSingleton(m_key, "count", m_count);
if (m_count > 0) {
callback.OutputSingleton(m_key, "total", m_total);
callback.OutputSingleton(m_key, "average", m_total/m_count);
callback.OutputSingleton(m_key, "max", m_max);
callback.OutputSingleton(m_key, "min", m_min);
}
// end MinMaxAvgTotalCalculator::Output
callback.OutputStatistic(m_context, m_key, this);
}
//------------------------------------------------------------
//--------------------------------------------
template <typename T = uint32_t>
@@ -178,7 +180,7 @@ namespace ns3 {
void
CounterCalculator<T>::Output(DataOutputCallback &callback) const
{
callback.OutputSingleton(m_key, "count", m_count);
callback.OutputSingleton(m_context, m_key, m_count);
// end CounterCalculator::Output
}

View File

@@ -27,6 +27,8 @@ using namespace ns3;
NS_LOG_COMPONENT_DEFINE("DataCalculator");
static double zero = 0;
const double ns3::NaN = zero / zero;
//--------------------------------------------------------------
//----------------------------------------------
@@ -68,6 +70,20 @@ DataCalculator::GetKey() const
// end DataCalculator::GetKey
}
//----------------------------------------------
void
DataCalculator::SetContext(const std::string context)
{
m_context = context;
// end DataCalculator::SetContext
}
std::string
DataCalculator::GetContext() const
{
return m_context;
// end DataCalculator::GetContext
}
//----------------------------------------------
void
DataCalculator::Enable()

View File

@@ -26,9 +26,56 @@
#include "ns3/simulator.h"
namespace ns3 {
extern const double NaN;
inline bool isNaN(double x) { return x != x; }
class DataOutputCallback;
class StatisticalSummary {
public:
/**
* Returns the number of the observations.
*/
virtual long getCount() const = 0;
/**
* Returns the sum of the values.
* @see getWeightedSum()
*/
virtual double getSum() const = 0;
/**
* Returns the sum of the squared values.
* @see getWeightedSqrSum()
*/
virtual double getSqrSum() const = 0;
/**
* Returns the minimum of the values.
*/
virtual double getMin() const = 0;
/**
* Returns the maximum of the values.
*/
virtual double getMax() const = 0;
/**
* Returns the mean of the (weighted) observations.
*/
virtual double getMean() const = 0;
/**
* Returns the standard deviation of the (weighted) observations.
*/
virtual double getStddev() const = 0;
/**
* Returns the variance of the (weighted) observations.
*/
virtual double getVariance() const = 0;
};
//------------------------------------------------------------
//--------------------------------------------
class DataCalculator : public Object {
@@ -43,6 +90,9 @@ namespace ns3 {
void SetKey(const std::string key);
std::string GetKey() const;
void SetContext(const std::string context);
std::string GetContext() const;
virtual void Start(const Time& startTime);
virtual void Stop(const Time& stopTime);
@@ -52,6 +102,7 @@ namespace ns3 {
bool m_enabled; // Descendant classes *must* check & respect m_enabled!
std::string m_key;
std::string m_context;
virtual void DoDispose(void);

View File

@@ -23,6 +23,7 @@
#include "ns3/object.h"
#include "ns3/nstime.h"
#include "ns3/data-calculator.h"
namespace ns3 {
@@ -52,6 +53,10 @@ namespace ns3 {
public:
virtual ~DataOutputCallback() {}
virtual void OutputStatistic(std::string key,
std::string variable,
const StatisticalSummary *statSum) = 0;
virtual void OutputSingleton(std::string key,
std::string variable,
int val) = 0;

View File

@@ -19,6 +19,7 @@
*/
#include <fstream>
#include <cstdlib>
#include "ns3/log.h"
#include "ns3/nstime.h"
@@ -54,26 +55,31 @@ OmnetDataOutput::DoDispose()
}
//----------------------------------------------
inline bool isNumeric(const std::string& s) {
char *endp;
strtod(s.c_str(), &endp);
return endp == s.c_str() + s.size();
}
void
OmnetDataOutput::Output(DataCollector &dc)
{
std::ofstream scalarFile;
std::string fn = m_filePrefix + ".sca";
scalarFile.open(fn.c_str(), std::ios_base::app);
std::string fn = m_filePrefix +"-"+dc.GetRunLabel()+ ".sca";
scalarFile.open(fn.c_str(), std::ios_base::out);
scalarFile << std::endl;
// TODO add timestamp to the runlevel
scalarFile << "run " << dc.GetRunLabel() << std::endl;
scalarFile << std::endl;
scalarFile << "attr experiment \"" << dc.GetExperimentLabel()
<< "\"" << std::endl;
scalarFile << "attr strategy \"" << dc.GetStrategyLabel()
<< "\"" << std::endl;
scalarFile << "attr input \"" << dc.GetInputLabel()
scalarFile << "attr measurement \"" << dc.GetInputLabel()
<< "\"" << std::endl;
scalarFile << "attr description \"" << dc.GetDescription()
<< "\"" << std::endl;
scalarFile << std::endl;
for (MetadataList::iterator i = dc.MetadataBegin();
i != dc.MetadataEnd(); i++) {
@@ -83,7 +89,18 @@ OmnetDataOutput::Output(DataCollector &dc)
}
scalarFile << std::endl;
if (isNumeric(dc.GetInputLabel())) {
scalarFile << "scalar . measurement \"" << dc.GetInputLabel()
<< "\"" << std::endl;
}
for (MetadataList::iterator i = dc.MetadataBegin();
i != dc.MetadataEnd(); i++) {
std::pair<std::string, std::string> blob = (*i);
if (isNumeric(blob.second)) {
scalarFile << "scalar . \"" << blob.first << "\" \"" << blob.second << "\""
<< std::endl;
}
}
OmnetOutputCallback callback(&scalarFile);
for (DataCalculatorList::iterator i = dc.DataCalculatorBegin();
@@ -97,6 +114,7 @@ OmnetDataOutput::Output(DataCollector &dc)
// end OmnetDataOutput::Output
}
OmnetDataOutput::OmnetOutputCallback::OmnetOutputCallback
(std::ostream *scalar) :
m_scalar(scalar)
@@ -104,42 +122,92 @@ OmnetDataOutput::OmnetOutputCallback::OmnetOutputCallback
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
std::string variable,
OmnetDataOutput::OmnetOutputCallback::OutputStatistic(std::string context,
std::string name,
const StatisticalSummary *statSum)
{
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "statistic " << context << " " << name << std::endl;
if (!isNaN(statSum->getCount()))
(*m_scalar) << "field count " << statSum->getCount() << std::endl;
if (!isNaN(statSum->getSum()))
(*m_scalar) << "field sum " << statSum->getSum() << std::endl;
if (!isNaN(statSum->getMean()))
(*m_scalar) << "field mean " << statSum->getMean() << std::endl;
if (!isNaN(statSum->getMin()))
(*m_scalar) << "field min " << statSum->getMin() << std::endl;
if (!isNaN(statSum->getMax()))
(*m_scalar) << "field max " << statSum->getMax() << std::endl;
if (!isNaN(statSum->getSqrSum()))
(*m_scalar) << "field sqrsum " << statSum->getSqrSum() << std::endl;
if (!isNaN(statSum->getStddev()))
(*m_scalar) << "field stddev " << statSum->getStddev() << std::endl;
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
std::string name,
int val)
{
(*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
std::string variable,
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
std::string name,
uint32_t val)
{
(*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
std::string variable,
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
std::string name,
double val)
{
(*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
std::string variable,
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
std::string name,
std::string val)
{
(*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
void
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
std::string variable,
OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
std::string name,
Time val)
{
(*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
if (context == "")
context = ".";
if (name == "")
name = "\"\"";
(*m_scalar) << "scalar " << context << " " << name << " " << val.GetTimeStep() << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}

View File

@@ -45,24 +45,28 @@ namespace ns3 {
public:
OmnetOutputCallback(std::ostream *scalar);
void OutputSingleton(std::string key,
std::string variable,
void OutputStatistic(std::string context,
std::string name,
const StatisticalSummary *statSum);
void OutputSingleton(std::string context,
std::string name,
int val);
void OutputSingleton(std::string key,
std::string variable,
void OutputSingleton(std::string context,
std::string name,
uint32_t val);
void OutputSingleton(std::string key,
std::string variable,
void OutputSingleton(std::string context,
std::string name,
double val);
void OutputSingleton(std::string key,
std::string variable,
void OutputSingleton(std::string context,
std::string name,
std::string val);
void OutputSingleton(std::string key,
std::string variable,
void OutputSingleton(std::string context,
std::string name,
Time val);
private:

View File

@@ -153,6 +153,25 @@ SqliteDataOutput::SqliteOutputCallback::SqliteOutputCallback
// end SqliteDataOutput::SqliteOutputCallback::SqliteOutputCallback
}
void
SqliteDataOutput::SqliteOutputCallback::OutputStatistic(std::string key,
std::string variable,
const StatisticalSummary *statSum)
{
OutputSingleton(key,variable+"-count", (double)statSum->getCount());
if (!isNaN(statSum->getSum()))
OutputSingleton(key,variable+"-total", statSum->getSum());
if (!isNaN(statSum->getMax()))
OutputSingleton(key,variable+"-max", statSum->getMax());
if (!isNaN(statSum->getMin()))
OutputSingleton(key,variable+"-min", statSum->getMin());
if (!isNaN(statSum->getSqrSum()))
OutputSingleton(key,variable+"-sqrsum", statSum->getSqrSum());
if (!isNaN(statSum->getStddev()))
OutputSingleton(key,variable+"-stddev", statSum->getStddev());
}
void
SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
std::string variable,

View File

@@ -48,6 +48,10 @@ namespace ns3 {
public:
SqliteOutputCallback(Ptr<SqliteDataOutput> owner, std::string run);
void OutputStatistic(std::string key,
std::string variable,
const StatisticalSummary *statSum);
void OutputSingleton(std::string key,
std::string variable,
int val);

View File

@@ -70,12 +70,12 @@ TimeMinMaxAvgTotalCalculator::Update(const Time i)
void
TimeMinMaxAvgTotalCalculator::Output(DataOutputCallback &callback) const
{
callback.OutputSingleton(m_key, "count", m_count);
callback.OutputSingleton(m_context, m_key + "-count", m_count);
if (m_count > 0) {
callback.OutputSingleton(m_key, "total", m_total);
callback.OutputSingleton(m_key, "average", m_total/Scalar(m_count));
callback.OutputSingleton(m_key, "max", m_max);
callback.OutputSingleton(m_key, "min", m_min);
callback.OutputSingleton(m_context, m_key + "-total", m_total);
callback.OutputSingleton(m_context, m_key + "-average", m_total/Scalar(m_count));
callback.OutputSingleton(m_context, m_key + "-max", m_max);
callback.OutputSingleton(m_context, m_key + "-min", m_min);
}
// end TimeMinMaxAvgTotalCalculator::Output
}