Add new response time/ utilisation metrics/plots and update CommandsLengths table
This commit is contained in:
@@ -306,10 +306,8 @@ void TlmRecorder::prepareSqlStatements()
|
||||
":mcconfig, :memspec, :traces, :windowSize, :refreshMaxPostponed, :refreshMaxPulledin, :controllerThread, "
|
||||
":maxBufferDepth, :per2BankOffset)";
|
||||
|
||||
insertCommandLengthsString =
|
||||
"INSERT INTO CommandLengths VALUES"
|
||||
"(:NOP, :RD, :WR, :RDA, :WRA, :ACT, :PREPB, :REFPB, :RFMPB, :REFP2B, :RFMP2B, :PRESB, :REFSB, :RFMSB, "
|
||||
":PREAB, :REFAB, :RFMAB, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)";
|
||||
insertCommandLengthsString = "INSERT INTO CommandLengths VALUES"
|
||||
"(:command, :length)";
|
||||
|
||||
insertDebugMessageString =
|
||||
"INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
|
||||
@@ -376,31 +374,17 @@ void TlmRecorder::insertCommandLengths()
|
||||
{
|
||||
const MemSpec *memSpec = Configuration::getInstance().memSpec;
|
||||
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 1, static_cast<int>(lround(memSpec->getCommandLength(Command::NOP) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 2, static_cast<int>(lround(memSpec->getCommandLength(Command::RD) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 3, static_cast<int>(lround(memSpec->getCommandLength(Command::WR) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 4, static_cast<int>(lround(memSpec->getCommandLength(Command::RDA) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 5, static_cast<int>(lround(memSpec->getCommandLength(Command::WRA) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 6, static_cast<int>(lround(memSpec->getCommandLength(Command::ACT) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 7, static_cast<int>(lround(memSpec->getCommandLength(Command::PREPB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 8, static_cast<int>(lround(memSpec->getCommandLength(Command::REFPB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 9, static_cast<int>(lround(memSpec->getCommandLength(Command::RFMPB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 10, static_cast<int>(lround(memSpec->getCommandLength(Command::REFP2B) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 11, static_cast<int>(lround(memSpec->getCommandLength(Command::RFMP2B) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 12, static_cast<int>(lround(memSpec->getCommandLength(Command::PRESB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 13, static_cast<int>(lround(memSpec->getCommandLength(Command::REFSB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 14, static_cast<int>(lround(memSpec->getCommandLength(Command::RFMSB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 15, static_cast<int>(lround(memSpec->getCommandLength(Command::PREAB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 16, static_cast<int>(lround(memSpec->getCommandLength(Command::REFAB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 17, static_cast<int>(lround(memSpec->getCommandLength(Command::RFMAB) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 18, static_cast<int>(lround(memSpec->getCommandLength(Command::PDEA) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 19, static_cast<int>(lround(memSpec->getCommandLength(Command::PDXA) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 20, static_cast<int>(lround(memSpec->getCommandLength(Command::PDEP) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 21, static_cast<int>(lround(memSpec->getCommandLength(Command::PDXP) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 22, static_cast<int>(lround(memSpec->getCommandLength(Command::SREFEN) / memSpec->tCK)));
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 23, static_cast<int>(lround(memSpec->getCommandLength(Command::SREFEX) / memSpec->tCK)));
|
||||
auto insertCommandLength = [this, memSpec](Command command) {
|
||||
auto commandName = command.toString();
|
||||
|
||||
executeSqlStatement(insertCommandLengthsStatement);
|
||||
sqlite3_bind_text(insertCommandLengthsStatement, 1, commandName.c_str(), commandName.length(), nullptr);
|
||||
sqlite3_bind_int(insertCommandLengthsStatement, 2,
|
||||
static_cast<int>(lround(memSpec->getCommandLength(command) / memSpec->tCK)));
|
||||
executeSqlStatement(insertCommandLengthsStatement);
|
||||
};
|
||||
|
||||
for (unsigned int command = 0; command < Command::END_ENUM; ++command)
|
||||
insertCommandLength(static_cast<Command::Type>(command));
|
||||
}
|
||||
|
||||
void TlmRecorder::insertTransactionInDB(Transaction &recordingData)
|
||||
|
||||
@@ -153,123 +153,102 @@ private:
|
||||
insertBufferDepthString, insertBandwidthString;
|
||||
|
||||
std::string initialCommand =
|
||||
"DROP TABLE IF EXISTS Phases; \n"
|
||||
"DROP TABLE IF EXISTS GeneralInfo; \n"
|
||||
"DROP TABLE IF EXISTS CommandLengths; \n"
|
||||
"DROP TABLE IF EXISTS Comments; \n"
|
||||
"DROP TABLE IF EXISTS ranges; \n"
|
||||
"DROP TABLE IF EXISTS Transactions; \n"
|
||||
"DROP TABLE IF EXISTS DebugMessages; \n"
|
||||
"DROP TABLE IF EXISTS Power; \n"
|
||||
"DROP TABLE IF EXISTS BufferDepth; \n"
|
||||
"DROP TABLE IF EXISTS Bandwidth; \n"
|
||||
" \n"
|
||||
"CREATE TABLE Phases( \n"
|
||||
" ID INTEGER PRIMARY KEY, \n"
|
||||
" PhaseName TEXT, \n"
|
||||
" PhaseBegin INTEGER, \n"
|
||||
" PhaseEnd INTEGER, \n"
|
||||
" Transact INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE GeneralInfo( \n"
|
||||
" NumberOfTransactions INTEGER, \n"
|
||||
" TraceEnd INTEGER, \n"
|
||||
" NumberOfRanks INTEGER, \n"
|
||||
" NumberOfBankgroups INTEGER, \n"
|
||||
" NumberOfBanks INTEGER, \n"
|
||||
" clk INTEGER, \n"
|
||||
" UnitOfTime TEXT, \n"
|
||||
" MCconfig TEXT, \n"
|
||||
" Memspec TEXT, \n"
|
||||
" Traces TEXT, \n"
|
||||
" WindowSize INTEGER, \n"
|
||||
" RefreshMaxPostponed INTEGER, \n"
|
||||
" RefreshMaxPulledin INTEGER, \n"
|
||||
" ControllerThread INTEGER, \n"
|
||||
" MaxBufferDepth INTEGER, \n"
|
||||
" Per2BankOffset INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE CommandLengths( \n"
|
||||
" NOP INTEGER, \n"
|
||||
" RD INTEGER, \n"
|
||||
" WR INTEGER, \n"
|
||||
" RDA INTEGER, \n"
|
||||
" WRA INTEGER, \n"
|
||||
" ACT INTEGER, \n"
|
||||
" PREPB INTEGER, \n"
|
||||
" REFPB INTEGER, \n"
|
||||
" RFMPB INTEGER, \n"
|
||||
" REFP2B INTEGER, \n"
|
||||
" RFMP2B INTEGER, \n"
|
||||
" PRESB INTEGER, \n"
|
||||
" REFSB INTEGER, \n"
|
||||
" RFMSB INTEGER, \n"
|
||||
" PREAB INTEGER, \n"
|
||||
" REFAB INTEGER, \n"
|
||||
" RFMAB INTEGER, \n"
|
||||
" PDEA INTEGER, \n"
|
||||
" PDXA INTEGER, \n"
|
||||
" PDEP INTEGER, \n"
|
||||
" PDXP INTEGER, \n"
|
||||
" SREFEN INTEGER, \n"
|
||||
" SREFEX INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Power( \n"
|
||||
" time DOUBLE, \n"
|
||||
" AveragePower DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE BufferDepth( \n"
|
||||
" Time DOUBLE, \n"
|
||||
" BufferNumber INTEGER, \n"
|
||||
" AverageBufferDepth DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Bandwidth( \n"
|
||||
" Time DOUBLE, \n"
|
||||
" AverageBandwidth DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Comments( \n"
|
||||
" Time INTEGER, \n"
|
||||
" Text TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE DebugMessages( \n"
|
||||
" Time INTEGER, \n"
|
||||
" Message TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"-- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html)\n"
|
||||
"CREATE VIRTUAL TABLE ranges USING rtree( \n"
|
||||
" id, \n"
|
||||
" begin, end \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Transactions( \n"
|
||||
" ID INTEGER, \n"
|
||||
" Range INTEGER, \n"
|
||||
" Address INTEGER, \n"
|
||||
" Burstlength INTEGER, \n"
|
||||
" TThread INTEGER, \n"
|
||||
" TChannel INTEGER, \n"
|
||||
" TRank INTEGER, \n"
|
||||
" TBankgroup INTEGER, \n"
|
||||
" TBank INTEGER, \n"
|
||||
" TRow INTEGER, \n"
|
||||
" TColumn INTEGER, \n"
|
||||
" DataStrobeBegin INTEGER, \n"
|
||||
" DataStrobeEnd INTEGER, \n"
|
||||
" TimeOfGeneration INTEGER, \n"
|
||||
" Command TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE INDEX ranges_index ON Transactions(Range); \n"
|
||||
"CREATE INDEX \"phasesTransactions\" ON \"Phases\" (\"Transact\" ASC); \n"
|
||||
"CREATE INDEX \"messageTimes\" ON \"DebugMessages\" (\"Time\" ASC); \n";
|
||||
"DROP TABLE IF EXISTS Phases; \n"
|
||||
"DROP TABLE IF EXISTS GeneralInfo; \n"
|
||||
"DROP TABLE IF EXISTS CommandLengths; \n"
|
||||
"DROP TABLE IF EXISTS Comments; \n"
|
||||
"DROP TABLE IF EXISTS ranges; \n"
|
||||
"DROP TABLE IF EXISTS Transactions; \n"
|
||||
"DROP TABLE IF EXISTS DebugMessages; \n"
|
||||
"DROP TABLE IF EXISTS Power; \n"
|
||||
"DROP TABLE IF EXISTS BufferDepth; \n"
|
||||
"DROP TABLE IF EXISTS Bandwidth; \n"
|
||||
" \n"
|
||||
"CREATE TABLE Phases( \n"
|
||||
" ID INTEGER PRIMARY KEY, \n"
|
||||
" PhaseName TEXT, \n"
|
||||
" PhaseBegin INTEGER, \n"
|
||||
" PhaseEnd INTEGER, \n"
|
||||
" Transact INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE GeneralInfo( \n"
|
||||
" NumberOfTransactions INTEGER, \n"
|
||||
" TraceEnd INTEGER, \n"
|
||||
" NumberOfRanks INTEGER, \n"
|
||||
" NumberOfBankgroups INTEGER, \n"
|
||||
" NumberOfBanks INTEGER, \n"
|
||||
" clk INTEGER, \n"
|
||||
" UnitOfTime TEXT, \n"
|
||||
" MCconfig TEXT, \n"
|
||||
" Memspec TEXT, \n"
|
||||
" Traces TEXT, \n"
|
||||
" WindowSize INTEGER, \n"
|
||||
" RefreshMaxPostponed INTEGER, \n"
|
||||
" RefreshMaxPulledin INTEGER, \n"
|
||||
" ControllerThread INTEGER, \n"
|
||||
" MaxBufferDepth INTEGER, \n"
|
||||
" Per2BankOffset INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE CommandLengths( \n"
|
||||
" Command TEXT, \n"
|
||||
" Length INTEGER \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Power( \n"
|
||||
" time DOUBLE, \n"
|
||||
" AveragePower DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE BufferDepth( \n"
|
||||
" Time DOUBLE, \n"
|
||||
" BufferNumber INTEGER, \n"
|
||||
" AverageBufferDepth DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Bandwidth( \n"
|
||||
" Time DOUBLE, \n"
|
||||
" AverageBandwidth DOUBLE \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Comments( \n"
|
||||
" Time INTEGER, \n"
|
||||
" Text TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE DebugMessages( \n"
|
||||
" Time INTEGER, \n"
|
||||
" Message TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"-- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html)\n"
|
||||
"CREATE VIRTUAL TABLE ranges USING rtree( \n"
|
||||
" id, \n"
|
||||
" begin, end \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE TABLE Transactions( \n"
|
||||
" ID INTEGER, \n"
|
||||
" Range INTEGER, \n"
|
||||
" Address INTEGER, \n"
|
||||
" Burstlength INTEGER, \n"
|
||||
" TThread INTEGER, \n"
|
||||
" TChannel INTEGER, \n"
|
||||
" TRank INTEGER, \n"
|
||||
" TBankgroup INTEGER, \n"
|
||||
" TBank INTEGER, \n"
|
||||
" TRow INTEGER, \n"
|
||||
" TColumn INTEGER, \n"
|
||||
" DataStrobeBegin INTEGER, \n"
|
||||
" DataStrobeEnd INTEGER, \n"
|
||||
" TimeOfGeneration INTEGER, \n"
|
||||
" Command TEXT \n"
|
||||
"); \n"
|
||||
" \n"
|
||||
"CREATE INDEX ranges_index ON Transactions(Range); \n"
|
||||
"CREATE INDEX \"phasesTransactions\" ON \"Phases\" (\"Transact\" ASC); \n"
|
||||
"CREATE INDEX \"messageTimes\" ON \"DebugMessages\" (\"Time\" ASC); \n";
|
||||
};
|
||||
|
||||
#endif // TLMRECORDER_H
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PythonCaller &PythonCaller::instance()
|
||||
{
|
||||
static PythonCaller instance;
|
||||
@@ -98,21 +96,20 @@ PythonCaller::PythonCaller() :
|
||||
|
||||
|
||||
//returns new reference to the function (see: http://edcjones.tripod.com/refcount.html for the difference between "new reference" and "borrowed reference")
|
||||
PyObject *PythonCaller::loadFunctionFromModule(string moduleName,
|
||||
string functionName)
|
||||
PyObject *PythonCaller::loadFunctionFromModule(std::string moduleName, std::string functionName)
|
||||
{
|
||||
PyObject *pModuleName = PyUnicode_FromString(moduleName.c_str());
|
||||
PyObject *pModule = PyImport_Import(pModuleName);
|
||||
|
||||
if (!pModule) {
|
||||
throw runtime_error(string("Could not load module " + moduleName));
|
||||
throw std::runtime_error(std::string("Could not load module " + moduleName));
|
||||
}
|
||||
|
||||
PyObject *pFunction = PyObject_GetAttrString(pModule, functionName.c_str());
|
||||
|
||||
if (!pFunction || !PyCallable_Check(pFunction)) {
|
||||
throw runtime_error(string("Could not load test function " + functionName +
|
||||
"in module " + moduleName));
|
||||
throw std::runtime_error(
|
||||
std::string("Could not load test function " + functionName + "in module " + moduleName));
|
||||
}
|
||||
|
||||
Py_DECREF(pModuleName);
|
||||
@@ -134,8 +131,7 @@ PythonCaller::~PythonCaller()
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
PyObject *PythonCaller::callMetricsFunction(PyObject *function,
|
||||
QString argument, vector<long> list)
|
||||
PyObject *PythonCaller::callMetricsFunction(PyObject *function, QString argument, std::vector<long> list)
|
||||
{
|
||||
assert(PyCallable_Check(function));
|
||||
|
||||
@@ -153,8 +149,7 @@ PyObject *PythonCaller::callMetricsFunction(PyObject *function,
|
||||
|
||||
if (!pResult) {
|
||||
PyErr_Print();
|
||||
throw runtime_error(string("Error in calling " + testFunctionName +
|
||||
" in module " + testModuleName));
|
||||
throw std::runtime_error(std::string("Error in calling " + testFunctionName + " in module " + testModuleName));
|
||||
}
|
||||
|
||||
return pResult;
|
||||
@@ -174,8 +169,7 @@ PyObject *PythonCaller::callFunctionWithStringArgument(PyObject *function,
|
||||
|
||||
if (!pResult) {
|
||||
PyErr_Print();
|
||||
throw runtime_error(string("Error in calling " + testFunctionName +
|
||||
" in module " + testModuleName));
|
||||
throw std::runtime_error(std::string("Error in calling " + testFunctionName + " in module " + testModuleName));
|
||||
}
|
||||
|
||||
return pResult;
|
||||
@@ -188,7 +182,7 @@ PyObject *PythonCaller::callFunctionWithoutArguments(PyObject *function)
|
||||
|
||||
if (!pResult) {
|
||||
PyErr_Print();
|
||||
throw runtime_error(string("Error in calling python function"));
|
||||
throw std::runtime_error(std::string("Error in calling python function"));
|
||||
}
|
||||
|
||||
return pResult;
|
||||
@@ -212,8 +206,7 @@ TraceTestResults PythonCaller::runTestsOnTrace(QString pathToTrace)
|
||||
return traceTestResult;
|
||||
}
|
||||
|
||||
TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(
|
||||
QString pathToTrace, vector<long> list)
|
||||
TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace, std::vector<long> list)
|
||||
{
|
||||
TraceCalculatedMetrics result(QFileInfo(pathToTrace).baseName());
|
||||
PyObject *pResult = callMetricsFunction(pCalculateMetricsFunction, pathToTrace,
|
||||
@@ -230,9 +223,9 @@ TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<string> PythonCaller::getMetrics(QString pathToTrace)
|
||||
std::vector<std::string> PythonCaller::getMetrics(QString pathToTrace)
|
||||
{
|
||||
vector<string> result;
|
||||
std::vector<std::string> result;
|
||||
PyObject *pResult = callFunctionWithStringArgument(pGetMetricsFunction,
|
||||
pathToTrace);
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ class PythonCaller
|
||||
{
|
||||
public:
|
||||
static PythonCaller &instance();
|
||||
PythonCaller(const PythonCaller &other) = delete;
|
||||
|
||||
TraceTestResults runTestsOnTrace(QString pathToTrace);
|
||||
TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace,
|
||||
@@ -70,6 +69,8 @@ public:
|
||||
private:
|
||||
PythonCaller();
|
||||
~PythonCaller();
|
||||
PythonCaller(const PythonCaller &other) = delete;
|
||||
PythonCaller &operator=(const PythonCaller &other) = delete;
|
||||
|
||||
PyObject *pRunTestsFunction, *pCalculateMetricsFunction, *pGetMetricsFunction;
|
||||
PyObject *pGenPlotsFunction;
|
||||
|
||||
@@ -54,6 +54,12 @@ def getNumberOfTransactions(dbconnection):
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
def getTraceEndTime(dbconnection):
|
||||
cursor = dbconnection.cursor()
|
||||
cursor.execute("SELECT TraceEnd FROM GeneralInfo")
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
def getNumberOfBanks(dbconnection):
|
||||
cursor = dbconnection.cursor()
|
||||
cursor.execute("SELECT NumberOfBanks FROM generalInfo")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import sys
|
||||
import sqlite3
|
||||
import argparse
|
||||
from memUtil import *
|
||||
from math import *
|
||||
|
||||
@@ -35,6 +36,23 @@ def trace_length_in_ns(connection):
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
@metric
|
||||
def command_bus_utilisation_in_percent(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
SUM(CommandLengths.Length)
|
||||
FROM
|
||||
Phases
|
||||
INNER JOIN
|
||||
CommandLengths
|
||||
ON Phases.PhaseName = CommandLengths.Command
|
||||
""")
|
||||
result = cursor.fetchone()[0]
|
||||
clk, _ = getClock(connection)
|
||||
traceEnd = getTraceEndTime(connection)
|
||||
cmdBusOccupied = result / clk * 1_000_000
|
||||
return cmdBusOccupied / traceEnd * 100
|
||||
|
||||
@metric
|
||||
def average_response_latency_in_ns(connection):
|
||||
@@ -44,11 +62,94 @@ def average_response_latency_in_ns(connection):
|
||||
result = cursor.fetchone()
|
||||
return round(result[0], 1)
|
||||
|
||||
@metric
|
||||
def average_rd_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND Transactions.Command = "R"
|
||||
""")
|
||||
result = cursor.fetchone()
|
||||
return round(result[0], 1)
|
||||
|
||||
@metric
|
||||
def average_wr_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND Transactions.Command = "W"
|
||||
""")
|
||||
result = cursor.fetchone()
|
||||
return round(result[0], 1)
|
||||
|
||||
@metric
|
||||
def max_rd_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND Transactions.Command = "R"
|
||||
""")
|
||||
result = cursor.fetchone()
|
||||
return round(result[0], 1)
|
||||
|
||||
@metric
|
||||
def max_wr_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND Transactions.Command = "W"
|
||||
""")
|
||||
result = cursor.fetchone()
|
||||
return round(result[0], 1)
|
||||
|
||||
@metric
|
||||
def max_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(""" SELECT max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP
|
||||
cursor.execute(""" SELECT max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP
|
||||
WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """)
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
@@ -995,8 +1096,6 @@ def calculateMetricsFromFuncs(pathToTrace, selectedMetrics):
|
||||
connection.close()
|
||||
return calculatedMetrics
|
||||
|
||||
import argparse
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
Only non-threaded metrics are implemented for selection through command line
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import sys
|
||||
import sqlite3
|
||||
from memUtil import *
|
||||
from math import *
|
||||
import ntpath
|
||||
import os
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from memUtil import *
|
||||
from math import *
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
numberOfBins = "auto"
|
||||
latencyRange = None
|
||||
|
||||
plots = []
|
||||
|
||||
def plot(function):
|
||||
plots.append(function)
|
||||
return function
|
||||
|
||||
def getThreads(connection):
|
||||
cursor = connection.cursor()
|
||||
@@ -95,13 +102,7 @@ def memory_utilisation_window_thread(connection, tracePath, steps, thread_ID):
|
||||
outputFileNameBWMatlab, basename = createOutputFilename(tracePath, 'memory_utilization_percent', 'thread_' + str(thread_ID) + '_', 'txt')
|
||||
return bandwidthPercentage, bandwidth, outputFileNameBWMatlab
|
||||
|
||||
|
||||
def plot(function):
|
||||
plots.append(function)
|
||||
return function
|
||||
|
||||
|
||||
#@plot
|
||||
@plot
|
||||
def memory_utilisation_window(connection, tracePath, steps):
|
||||
# This function determines the average memory bandwidth over time in
|
||||
# percentage and in Gbit/s. The average bandwidth over time is done
|
||||
@@ -131,10 +132,6 @@ def memory_utilisation_window(connection, tracePath, steps):
|
||||
outputFileNameBWMatlab, basename = createOutputFilename(tracePath, 'memory_utilization_percent', '', 'txt')
|
||||
outputFiles = "{0}\n\t{1}\n\t{2}\n\t".format(outputFileNameGBPS, outputFileNamePercent, outputFileNameBWMatlab)
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
# windowSize/1000: picoseconds to nanoseconds conversion
|
||||
time = np.arange(0, (steps+1)*windowSize/1000, windowSize/1000)
|
||||
maxBandwidth = [maxDataRate/1024] * (steps+1)
|
||||
@@ -196,12 +193,209 @@ def memory_utilisation_window(connection, tracePath, steps):
|
||||
|
||||
return outputFiles
|
||||
|
||||
@plot
|
||||
def response_latency_window(connection, tracePath, steps):
|
||||
windowSize = getWindowSize(connection)
|
||||
|
||||
cursor = connection.cursor()
|
||||
query = """
|
||||
SELECT
|
||||
avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ?
|
||||
"""
|
||||
outputFileName, basename = createOutputFilename(tracePath, 'response_latency', '', 'pdf')
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
|
||||
LatencyFigure = plt.figure(figsize=(10, 5), dpi=300)
|
||||
LatencyFigurePlot = LatencyFigure.add_subplot(111)
|
||||
LatencyFigurePlot.set_xlabel('Time [ns]')
|
||||
LatencyFigurePlot.set_ylabel('Response Latency [ns]')
|
||||
LatencyFigurePlot.set_title('Average Response Latency: ' + str(basename))
|
||||
LatencyFigurePlot.grid(True)
|
||||
|
||||
time = [None] * steps
|
||||
latency = [None] * steps
|
||||
|
||||
for i in range(steps):
|
||||
cursor.execute(query, (i * windowSize, (i + 1) * windowSize))
|
||||
result = cursor.fetchone()[0]
|
||||
time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns
|
||||
latency[i] = result
|
||||
|
||||
LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency")
|
||||
LatencyFigurePlot.legend(loc="upper left")
|
||||
|
||||
pdf = PdfPages(outputFileName)
|
||||
pdf.savefig(LatencyFigure)
|
||||
pdf.close()
|
||||
LatencyFigurePlot.clear()
|
||||
plt.close()
|
||||
|
||||
return outputFile
|
||||
|
||||
@plot
|
||||
def wr_response_latency_window(connection, tracePath, steps):
|
||||
windowSize = getWindowSize(connection)
|
||||
|
||||
cursor = connection.cursor()
|
||||
query = """
|
||||
SELECT
|
||||
avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ?
|
||||
AND Transactions.Command = "W"
|
||||
"""
|
||||
outputFileName, basename = createOutputFilename(tracePath, 'wr_response_latency', '', 'pdf')
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
|
||||
LatencyFigure = plt.figure(figsize=(10, 5), dpi=300)
|
||||
LatencyFigurePlot = LatencyFigure.add_subplot(111)
|
||||
LatencyFigurePlot.set_xlabel('Time [ns]')
|
||||
LatencyFigurePlot.set_ylabel('Response Latency [ns]')
|
||||
LatencyFigurePlot.set_title('Average Write Response Latency: ' + str(basename))
|
||||
LatencyFigurePlot.grid(True)
|
||||
|
||||
time = [None] * steps
|
||||
latency = [None] * steps
|
||||
|
||||
for i in range(steps):
|
||||
cursor.execute(query, (i * windowSize, (i + 1) * windowSize))
|
||||
result = cursor.fetchone()[0]
|
||||
time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns
|
||||
latency[i] = result
|
||||
|
||||
LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency")
|
||||
LatencyFigurePlot.legend(loc="upper left")
|
||||
|
||||
pdf = PdfPages(outputFileName)
|
||||
pdf.savefig(LatencyFigure)
|
||||
pdf.close()
|
||||
LatencyFigurePlot.clear()
|
||||
plt.close()
|
||||
|
||||
return outputFile
|
||||
|
||||
@plot
|
||||
def rd_response_latency_window(connection, tracePath, steps):
|
||||
windowSize = getWindowSize(connection)
|
||||
|
||||
cursor = connection.cursor()
|
||||
query = """
|
||||
SELECT
|
||||
avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
|
||||
FROM
|
||||
PHASES REQ,
|
||||
PHASES RESP
|
||||
INNER JOIN
|
||||
Transactions
|
||||
ON REQ.TRANSACT = Transactions.ID
|
||||
WHERE
|
||||
REQ.PHASENAME = 'REQ'
|
||||
AND RESP.PHASENAME = 'RESP'
|
||||
AND REQ.TRANSACT = RESP.TRANSACT
|
||||
AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ?
|
||||
AND Transactions.Command = "R"
|
||||
"""
|
||||
outputFileName, basename = createOutputFilename(tracePath, 'rd_response_latency', '', 'pdf')
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
|
||||
LatencyFigure = plt.figure(figsize=(10, 5), dpi=300)
|
||||
LatencyFigurePlot = LatencyFigure.add_subplot(111)
|
||||
LatencyFigurePlot.set_xlabel('Time [ns]')
|
||||
LatencyFigurePlot.set_ylabel('Response Latency [ns]')
|
||||
LatencyFigurePlot.set_title('Average Read Response Latency: ' + str(basename))
|
||||
LatencyFigurePlot.grid(True)
|
||||
|
||||
time = [None] * steps
|
||||
latency = [None] * steps
|
||||
|
||||
for i in range(steps):
|
||||
cursor.execute(query, (i * windowSize, (i + 1) * windowSize))
|
||||
result = cursor.fetchone()[0]
|
||||
time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns
|
||||
latency[i] = result
|
||||
|
||||
LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency")
|
||||
LatencyFigurePlot.legend(loc="upper left")
|
||||
|
||||
pdf = PdfPages(outputFileName)
|
||||
pdf.savefig(LatencyFigure)
|
||||
pdf.close()
|
||||
LatencyFigurePlot.clear()
|
||||
plt.close()
|
||||
|
||||
return outputFile
|
||||
|
||||
@plot
|
||||
def command_bus_utilisation_window(connection, tracePath, steps):
|
||||
windowSize = getWindowSize(connection)
|
||||
|
||||
cursor = connection.cursor()
|
||||
query = """
|
||||
SELECT
|
||||
SUM(CommandLengths.Length)
|
||||
FROM
|
||||
Phases
|
||||
INNER JOIN
|
||||
CommandLengths
|
||||
ON Phases.PhaseName = CommandLengths.Command
|
||||
WHERE
|
||||
Phases.PhaseBegin >= ?
|
||||
AND Phases.PhaseBegin < ?
|
||||
"""
|
||||
|
||||
outputFileName, basename = createOutputFilename(tracePath, 'command_bus_utilisation', '', 'pdf')
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
|
||||
LatencyFigure = plt.figure(figsize=(10, 5), dpi=300)
|
||||
LatencyFigurePlot = LatencyFigure.add_subplot(111)
|
||||
LatencyFigurePlot.set_xlabel('Time [ns]')
|
||||
LatencyFigurePlot.set_ylabel('Utilization [%]')
|
||||
LatencyFigurePlot.set_title('Command Bus Utilization: ' + str(basename))
|
||||
LatencyFigurePlot.grid(True)
|
||||
|
||||
clk, _ = getClock(connection)
|
||||
|
||||
time = [None] * steps
|
||||
utilization = [None] * steps
|
||||
|
||||
for i in range(steps):
|
||||
cursor.execute(query, (i * windowSize, (i + 1) * windowSize))
|
||||
result = cursor.fetchone()[0]
|
||||
cmdBusOccupied = result / clk * 1_000_000
|
||||
|
||||
time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns
|
||||
utilization[i] = cmdBusOccupied / windowSize * 100
|
||||
|
||||
LatencyFigurePlot.plot(time, utilization, linewidth=0.5, label="Utilization")
|
||||
LatencyFigurePlot.legend(loc="upper left")
|
||||
|
||||
pdf = PdfPages(outputFileName)
|
||||
pdf.savefig(LatencyFigure)
|
||||
pdf.close()
|
||||
LatencyFigurePlot.clear()
|
||||
plt.close()
|
||||
|
||||
return outputFile
|
||||
|
||||
@plot
|
||||
def queue_window(connection, tracePath, steps):
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("select max(BufferNumber) from BufferDepth;")
|
||||
bufferNumber = int(cursor.fetchone()[0]) + 1
|
||||
@@ -256,7 +450,6 @@ def power_window(connection, tracePath, steps):
|
||||
|
||||
cursor.execute(" SELECT * FROM Power")
|
||||
|
||||
import numpy as np
|
||||
window = float(windowSize) / pow(10, 12)
|
||||
time = np.arange(0, (windowSize * (steps + 1)) / pow(10, 6), windowSize / pow(10, 6))
|
||||
power = np.full(len(time), 0)
|
||||
@@ -282,9 +475,6 @@ def power_window(connection, tracePath, steps):
|
||||
outputFileName, basename = createOutputFilename(tracePath, 'power', '', 'pdf')
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
PowFigure = plt.figure(figsize=(10, 5), dpi=300)
|
||||
PowFigurePlot = PowFigure.add_subplot(111)
|
||||
PowFigurePlot.set_xlabel('Time [us]')
|
||||
@@ -301,104 +491,6 @@ def power_window(connection, tracePath, steps):
|
||||
|
||||
return outputFile
|
||||
|
||||
def latency_analysis(connection, tracePath, steps):
|
||||
from collections import Counter
|
||||
query = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000), t.id
|
||||
FROM Transactions t, Phases p1, Phases p2
|
||||
WHERE t.id = p1.Transact
|
||||
AND t.id = p2.Transact
|
||||
AND p1.PhaseName = "REQ"
|
||||
AND p2.PhaseName = "RESP" """
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
results = []
|
||||
while True:
|
||||
result = cursor.fetchone()
|
||||
if (result is not None):
|
||||
results.append([result[0], result[1]])
|
||||
else:
|
||||
break
|
||||
|
||||
# Create histogram for analysis:
|
||||
hist = {}
|
||||
transactions = {}
|
||||
for i in results:
|
||||
hist[i[0]] = hist.get(i[0], 0) + 1
|
||||
if i[0] in transactions:
|
||||
transactions[i[0]].append(i[1])
|
||||
else:
|
||||
transactions[i[0]] = []
|
||||
|
||||
# Find N highest bins
|
||||
N = 3
|
||||
k = Counter(hist)
|
||||
high = k.most_common(3)
|
||||
|
||||
for i in high:
|
||||
print(i[0]," :",i[1]," ")
|
||||
print(transactions[i[0]])
|
||||
|
||||
return "none\n"
|
||||
|
||||
#@plot
|
||||
def latency_histogram(connection, tracePath, steps):
|
||||
# This function plots an histogram with access latencys
|
||||
|
||||
def plot_latency_histogram(dataArray, outputFileName, basename):
|
||||
# plot into PDF file
|
||||
import matplotlib
|
||||
matplotlib.use('TkAgg')
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
plt.hist(dataArray, bins=numberOfBins, range=latencyRange, histtype='bar', facecolor='green')
|
||||
plt.grid(True)
|
||||
plt.xlabel("Access Time [ns]")
|
||||
plt.ylabel("Number of Accesses (Frequency)")
|
||||
plt.title("Latency Histogram " + str(basename))
|
||||
pdf = PdfPages(outputFileName)
|
||||
pdf.savefig()
|
||||
pdf.close()
|
||||
plt.close()
|
||||
|
||||
def create_latency_hist(connection, tracePath, target_measurement, query):
|
||||
# form output file name
|
||||
ofbname = 'access_latency_hist'
|
||||
outputFileName, basename = createOutputFilename(tracePath, ofbname, target_measurement, 'pdf')
|
||||
# return log string
|
||||
outputFile = "{0}\n\t".format(outputFileName)
|
||||
# access database
|
||||
resultArray = accessDatabase(connection, query)
|
||||
# plot
|
||||
plot_latency_histogram(resultArray, outputFileName, basename)
|
||||
return outputFile
|
||||
|
||||
# create overal latency histogram
|
||||
query = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000)
|
||||
FROM Transactions t, Phases p1, Phases p2
|
||||
WHERE t.id = p1.Transact
|
||||
AND t.id = p2.Transact
|
||||
AND p1.PhaseName = "REQ"
|
||||
AND p2.PhaseName = "RESP" """
|
||||
outputFile = create_latency_hist(connection, tracePath, '', query)
|
||||
|
||||
# create per-thread latency histogram
|
||||
threads = getThreads(connection)
|
||||
if (len(threads) > 1):
|
||||
queryThread = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000)
|
||||
FROM Transactions t, Phases p1, Phases p2
|
||||
WHERE t.id = p1.Transact
|
||||
AND t.id = p2.Transact
|
||||
AND p1.PhaseName = "REQ"
|
||||
AND p2.PhaseName = "RESP"
|
||||
AND t.TThread = {0} """
|
||||
for thread in threads:
|
||||
thrname = 'thread_' + str(thread) + '_'
|
||||
outputFile += create_latency_hist(connection, tracePath, thrname, queryThread.format(thread))
|
||||
|
||||
return outputFile
|
||||
|
||||
|
||||
def generatePlots(pathToTrace):
|
||||
connection = sqlite3.connect(pathToTrace)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user