summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <mail@milianw.de>2012-03-15 12:25:15 (GMT)
committerMilian Wolff <mail@milianw.de>2012-03-15 12:25:15 (GMT)
commit11a5f3247019d04c1b99547404a789b7095fceed (patch)
tree1e8574e58e1e197ccf525cc1a3dd8437a723a6cf
parent8117c5ac69794dc4eabc77a42dc84b65140634cc (diff)
optimize: drastically reduce memory footprint by using QByteArray instead of QString
we only convert to QString on demand when we actually display a string to the user. most often, this is just a small subset of the data we have lying around in total. the memory consumption gain is esp. noticeable for big data files, where it reduces the memory consumption by ~40%
-rw-r--r--app/mainwindow.cpp4
-rw-r--r--massifdata/parser.cpp2
-rw-r--r--massifdata/parser.h4
-rw-r--r--massifdata/parserprivate.cpp22
-rw-r--r--massifdata/treeleafitem.cpp4
-rw-r--r--massifdata/treeleafitem.h6
-rw-r--r--massifdata/util.cpp14
-rw-r--r--massifdata/util.h8
-rw-r--r--test/datamodeltest.cpp37
-rw-r--r--visualizer/datatreemodel.cpp2
-rw-r--r--visualizer/detailedcostmodel.cpp10
-rw-r--r--visualizer/detailedcostmodel.h4
-rw-r--r--visualizer/dotgraphgenerator.cpp2
13 files changed, 64 insertions, 55 deletions
diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp
index 25d03be..9988ae5 100644
--- a/app/mainwindow.cpp
+++ b/app/mainwindow.cpp
@@ -422,7 +422,9 @@ void MainWindow::openFile(const KUrl& file)
m_data = p.parse(device, m_allocatorModel->stringList());
if (!m_data) {
KMessageBox::error(this, i18n("Could not parse file <i>%1</i>.<br>"
- "Parse error in line %2:<br>%3", file.toLocalFile(), p.errorLine() + 1, p.errorLineString()),
+ "Parse error in line %2:<br>%3",
+ file.toLocalFile(), p.errorLine() + 1,
+ QString::fromLatin1(p.errorLineString())),
i18n("Could Not Parse File"));
setUpdatesEnabled(true);
return;
diff --git a/massifdata/parser.cpp b/massifdata/parser.cpp
index 12c09bf..42ee964 100644
--- a/massifdata/parser.cpp
+++ b/massifdata/parser.cpp
@@ -92,7 +92,7 @@ int Parser::errorLine() const
return m_errorLine;
}
-QString Parser::errorLineString() const
+QByteArray Parser::errorLineString() const
{
return m_errorLineString;
}
diff --git a/massifdata/parser.h b/massifdata/parser.h
index 0ec399f..8ba582d 100644
--- a/massifdata/parser.h
+++ b/massifdata/parser.h
@@ -62,11 +62,11 @@ public:
/**
* Returns the line which could not be parsed.
*/
- QString errorLineString() const;
+ QByteArray errorLineString() const;
private:
int m_errorLine;
- QString m_errorLineString;
+ QByteArray m_errorLineString;
};
}
diff --git a/massifdata/parserprivate.cpp b/massifdata/parserprivate.cpp
index 0078c14..cc4fc43 100644
--- a/massifdata/parserprivate.cpp
+++ b/massifdata/parserprivate.cpp
@@ -162,7 +162,7 @@ void ParserPrivate::parseSnapshot(const QByteArray& line)
++m_currentLine;
VALIDATE(nextLine.startsWith("snapshot="))
nextLine.chop(1);
- QString i(nextLine.mid(9));
+ QByteArray i(nextLine.mid(9));
bool ok;
uint number = i.toUInt(&ok);
VALIDATE(ok)
@@ -179,7 +179,7 @@ void ParserPrivate::parseSnapshot(const QByteArray& line)
void ParserPrivate::parseSnapshotTime(const QByteArray& line)
{
VALIDATE(line.startsWith("time="))
- QString timeStr(line.mid(5));
+ QByteArray timeStr(line.mid(5));
bool ok;
double time = timeStr.toDouble(&ok);
VALIDATE(ok)
@@ -190,7 +190,7 @@ void ParserPrivate::parseSnapshotTime(const QByteArray& line)
void ParserPrivate::parseSnapshotMemHeap(const QByteArray& line)
{
VALIDATE(line.startsWith("mem_heap_B="))
- QString byteStr(line.mid(11));
+ QByteArray byteStr(line.mid(11));
bool ok;
quint64 bytes = byteStr.toULongLong(&ok);
VALIDATE(ok)
@@ -201,7 +201,7 @@ void ParserPrivate::parseSnapshotMemHeap(const QByteArray& line)
void ParserPrivate::parseSnapshotMemHeapExtra(const QByteArray& line)
{
VALIDATE(line.startsWith("mem_heap_extra_B="))
- QString byteStr(line.mid(17));
+ QByteArray byteStr(line.mid(17));
bool ok;
quint64 bytes = byteStr.toULongLong(&ok);
VALIDATE(ok)
@@ -212,7 +212,7 @@ void ParserPrivate::parseSnapshotMemHeapExtra(const QByteArray& line)
void ParserPrivate::parseSnapshotMemStacks(const QByteArray& line)
{
VALIDATE(line.startsWith("mem_stacks_B="))
- QString byteStr(line.mid(13));
+ QByteArray byteStr(line.mid(13));
bool ok;
quint64 bytes = byteStr.toULongLong(&ok);
VALIDATE(ok)
@@ -259,21 +259,23 @@ void ParserPrivate::parseHeapTreeLeaf(const QByteArray& line)
static QRegExp matchBT("in ([0-9]+) places, all below massif's threshold",
Qt::CaseSensitive, QRegExp::RegExp2);
foreach(TreeLeafItem* child, newChildren) {
- if (child->label().indexOf(matchBT) != -1) {
+ if (matchBT.indexIn(QString::fromLatin1(child->label())) != -1) {
places += matchBT.cap(1).toUInt();
if (belowThreshold) {
+ // merge with previously found node
belowThreshold->setCost(belowThreshold->cost() + child->cost());
newChildren.removeOne(child);
delete child;
} else {
belowThreshold = child;
oldPlaces = matchBT.cap(1);
+ // no break, see above
}
}
}
if (belowThreshold) {
- QString label = belowThreshold->label();
- label.replace(oldPlaces, QString::number(places));
+ QByteArray label = belowThreshold->label();
+ label.replace(oldPlaces, QByteArray::number(places));
belowThreshold->setLabel(label);
}
qSort(newChildren.begin(), newChildren.end(), sortLeafsByCost);
@@ -320,12 +322,12 @@ bool ParserPrivate::parseheapTreeLeafInternal(const QByteArray& line, int depth)
return true;
}
- const QString label = line.mid(spacePos + 1);
+ const QByteArray label = line.mid(spacePos + 1);
bool isCustomAlloc = false;
if (depth > 0 && !m_allocators.isEmpty()) {
- const QString func = functionInLabel(label);
+ const QByteArray func = functionInLabel(label);
foreach(const QRegExp& allocator, m_allocators) {
if (allocator.exactMatch(func)) {
isCustomAlloc = true;
diff --git a/massifdata/treeleafitem.cpp b/massifdata/treeleafitem.cpp
index c9b2320..619c315 100644
--- a/massifdata/treeleafitem.cpp
+++ b/massifdata/treeleafitem.cpp
@@ -34,12 +34,12 @@ TreeLeafItem::~TreeLeafItem()
qDeleteAll(m_children);
}
-void TreeLeafItem::setLabel(const QString label)
+void TreeLeafItem::setLabel(const QByteArray& label)
{
m_label = label;
}
-QString TreeLeafItem::label() const
+QByteArray TreeLeafItem::label() const
{
return m_label;
}
diff --git a/massifdata/treeleafitem.h b/massifdata/treeleafitem.h
index be28471..95c3498 100644
--- a/massifdata/treeleafitem.h
+++ b/massifdata/treeleafitem.h
@@ -40,11 +40,11 @@ public:
/**
* Sets the label for this leaf item.
*/
- void setLabel(const QString label);
+ void setLabel(const QByteArray& label);
/**
* @return The label for this leaf item.
*/
- QString label() const;
+ QByteArray label() const;
/**
* Sets the cost for this item in bytes.
@@ -79,7 +79,7 @@ public:
TreeLeafItem* parent() const;
private:
- QString m_label;
+ QByteArray m_label;
quint64 m_cost;
QList<TreeLeafItem*> m_children;
diff --git a/massifdata/util.cpp b/massifdata/util.cpp
index cbe92be..10495b0 100644
--- a/massifdata/util.cpp
+++ b/massifdata/util.cpp
@@ -42,9 +42,9 @@ QString prettyCost(quint64 cost)
return KGlobal::locale()->formatByteSize(cost, precision);
}
-QString prettyLabel(const QString& label)
+QByteArray prettyLabel(const QByteArray& label)
{
- QString ret;
+ QByteArray ret;
int colonPos = label.indexOf(": ");
if (colonPos == -1) {
@@ -79,9 +79,9 @@ QString prettyLabel(const QString& label)
return ret;
}
-QString functionInLabel(const QString& label)
+QByteArray functionInLabel(const QByteArray& label)
{
- QString ret = prettyLabel(label);
+ QByteArray ret = prettyLabel(label);
int pos = ret.lastIndexOf(" (");
if (pos != -1) {
ret.resize(pos);
@@ -89,12 +89,12 @@ QString functionInLabel(const QString& label)
return ret;
}
-bool isBelowThreshold(const QString& label)
+bool isBelowThreshold(const QByteArray& label)
{
return label.indexOf("all below massif's threshold") != -1;
}
-QString formatLabel(const QString& label)
+QString formatLabel(const QByteArray& label)
{
static QRegExp pattern("^(0x.+: )?([^\\)]+\\))(?: \\(([^\\)]+)\\))?$", Qt::CaseSensitive,
QRegExp::RegExp2);
@@ -116,7 +116,7 @@ QString formatLabel(const QString& label)
}
}
-QString tooltipForTreeLeaf(TreeLeafItem* node, SnapshotItem* snapshot, const QString& label)
+QString tooltipForTreeLeaf(TreeLeafItem* node, SnapshotItem* snapshot, const QByteArray& label)
{
QString tooltip = "<html><head><style>dt{font-weight:bold;} dd {font-family:monospace;}</style></head><body><dl>\n";
tooltip += i18n("<dt>cost:</dt><dd>%1, i.e. %2% of snapshot #%3</dd>", prettyCost(node ? node->cost() : 0),
diff --git a/massifdata/util.h b/massifdata/util.h
index fbfad32..1f6496c 100644
--- a/massifdata/util.h
+++ b/massifdata/util.h
@@ -41,23 +41,23 @@ MASSIFDATA_EXPORT QString prettyCost(quint64 cost);
* Prepares a tree node's label for the UI.
* So far, only the Mem-Adress will get stripped.
*/
-MASSIFDATA_EXPORT QString prettyLabel(const QString& label);
+MASSIFDATA_EXPORT QByteArray prettyLabel(const QByteArray& label);
/**
* Extracts the function name from the @p label
*/
-MASSIFDATA_EXPORT QString functionInLabel(const QString& label);
+MASSIFDATA_EXPORT QByteArray functionInLabel(const QByteArray& label);
/**
* Checks whether this label denotes a tree node
* with aggregated items below massif's threshold.
*/
-MASSIFDATA_EXPORT bool isBelowThreshold(const QString& label);
+MASSIFDATA_EXPORT bool isBelowThreshold(const QByteArray& label);
/**
* Formats a label with richtext for showing in tooltips e.g.
*/
-MASSIFDATA_EXPORT QString tooltipForTreeLeaf(Massif::TreeLeafItem* node, Massif::SnapshotItem* snapshot, const QString& label);
+MASSIFDATA_EXPORT QString tooltipForTreeLeaf(Massif::TreeLeafItem* node, Massif::SnapshotItem* snapshot, const QByteArray& label);
}
diff --git a/test/datamodeltest.cpp b/test/datamodeltest.cpp
index 26464d6..83c66f8 100644
--- a/test/datamodeltest.cpp
+++ b/test/datamodeltest.cpp
@@ -101,33 +101,38 @@ void DataModelTest::parseFile()
void DataModelTest::testUtils()
{
{
- QString l("0x6F675AB: KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&) (identifier.cpp:1050)");
- QCOMPARE(prettyLabel(l), QString("KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&) (identifier.cpp:1050)"));
- QCOMPARE(functionInLabel(l), QString("KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&)"));
+ QByteArray l("0x6F675AB: KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&) (identifier.cpp:1050)");
+ QCOMPARE(prettyLabel(l), QByteArray("KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&) (identifier.cpp:1050)"));
+ QCOMPARE(functionInLabel(l), QByteArray("KDevelop::IndexedIdentifier::IndexedIdentifier(KDevelop::Identifier const&)"));
}
{
- QString l("0x6F675AB: moz_xmalloc (mozalloc.cpp:98)");
- QCOMPARE(prettyLabel(l), QString("moz_xmalloc (mozalloc.cpp:98)"));
- QCOMPARE(functionInLabel(l), QString("moz_xmalloc"));
+ QByteArray l("0x6F675AB: moz_xmalloc (mozalloc.cpp:98)");
+ QCOMPARE(prettyLabel(l), QByteArray("moz_xmalloc (mozalloc.cpp:98)"));
+ QCOMPARE(functionInLabel(l), QByteArray("moz_xmalloc"));
}
}
void DataModelTest::shortenTemplates_data()
{
- QTest::addColumn<QString>("id");
- QTest::addColumn<QString>("idShortened");
-
- QTest::newRow("no-tpl") << "A::B(C::D const&) (file.cpp:1)" << "A::B(C::D const&) (file.cpp:1)";
- QTest::newRow("tpl-func") << "A::B<T1, T2>(C::D const&) (file.cpp:1)" << "A::B<>(C::D const&) (file.cpp:1)";
- QTest::newRow("tpl-arg") << "A::B(C::D<T1, T2> const&) (file.cpp:1)" << "A::B(C::D<> const&) (file.cpp:1)";
- QTest::newRow("tpl-multi") << "A::B<T1, T2>(C<T3>::D<T4> const&) (file.cpp:1)" << "A::B<>(C<>::D<> const&) (file.cpp:1)";
- QTest::newRow("tpl-nested") << "A::B<T1<T2>, T2>(C<T3>::D<T4> const&) (file.cpp:1)" << "A::B<>(C<>::D<> const&) (file.cpp:1)";
+ QTest::addColumn<QByteArray>("id");
+ QTest::addColumn<QByteArray>("idShortened");
+
+ QTest::newRow("no-tpl") << QByteArray("A::B(C::D const&) (file.cpp:1)")
+ << QByteArray("A::B(C::D const&) (file.cpp:1)");
+ QTest::newRow("tpl-func") << QByteArray("A::B<T1, T2>(C::D const&) (file.cpp:1)")
+ << QByteArray("A::B<>(C::D const&) (file.cpp:1)");
+ QTest::newRow("tpl-arg") << QByteArray("A::B(C::D<T1, T2> const&) (file.cpp:1)")
+ << QByteArray("A::B(C::D<> const&) (file.cpp:1)");
+ QTest::newRow("tpl-multi") << QByteArray("A::B<T1, T2>(C<T3>::D<T4> const&) (file.cpp:1)")
+ << QByteArray("A::B<>(C<>::D<> const&) (file.cpp:1)");
+ QTest::newRow("tpl-nested") << QByteArray("A::B<T1<T2>, T2>(C<T3>::D<T4> const&) (file.cpp:1)")
+ << QByteArray("A::B<>(C<>::D<> const&) (file.cpp:1)");
}
void DataModelTest::shortenTemplates()
{
- QFETCH(QString, id);
- QFETCH(QString, idShortened);
+ QFETCH(QByteArray, id);
+ QFETCH(QByteArray, idShortened);
KConfigGroup conf = KGlobal::config()->group(QLatin1String("Settings"));
diff --git a/visualizer/datatreemodel.cpp b/visualizer/datatreemodel.cpp
index e728cb0..73ef04d 100644
--- a/visualizer/datatreemodel.cpp
+++ b/visualizer/datatreemodel.cpp
@@ -159,7 +159,7 @@ QVariant DataTreeModel::data(const QModelIndex& index, int role) const
return tooltipForTreeLeaf(item, snapshotForTreeLeaf(item), item->label());
}
return i18nc("%1: cost, %2: snapshot label (i.e. func name etc.)", "%1: %2",
- prettyCost(item->cost()), prettyLabel(item->label()));
+ prettyCost(item->cost()), QString::fromLatin1(prettyLabel(item->label())));
}
return QVariant();
}
diff --git a/visualizer/detailedcostmodel.cpp b/visualizer/detailedcostmodel.cpp
index df1c608..1e9c5be 100644
--- a/visualizer/detailedcostmodel.cpp
+++ b/visualizer/detailedcostmodel.cpp
@@ -67,7 +67,7 @@ void DetailedCostModel::setSource(const FileData* data)
if (data) {
// get top cost points:
// we traverse the detailed heap trees until the first fork
- QMultiMap<int, QString> sortColumnMap;
+ QMultiMap<int, QByteArray> sortColumnMap;
foreach (SnapshotItem* snapshot, data->snapshots()) {
if (snapshot->heapTree()) {
QList<TreeLeafItem*> nodes;
@@ -217,7 +217,7 @@ QVariant DetailedCostModel::data(const QModelIndex& index, int role) const
return snapshot->time();
} else {
TreeLeafItem* node = 0;
- const QString needle = m_columns.at(index.column() / 2);
+ const QByteArray needle = m_columns.at(index.column() / 2);
foreach(TreeLeafItem* n, m_nodes[snapshot]) {
if (n->label() == needle) {
node = n;
@@ -236,7 +236,7 @@ QVariant DetailedCostModel::headerData(int section, Qt::Orientation orientation,
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section % 2 == 0 && section < columnCount()) {
// only show name without memory address or location
- QString label = prettyLabel(m_columns.at(section / 2));
+ QByteArray label = prettyLabel(m_columns.at(section / 2));
if (label.indexOf("???") != -1) {
return label;
}
@@ -277,7 +277,7 @@ int DetailedCostModel::rowCount(const QModelIndex& parent) const
QMap< QModelIndex, TreeLeafItem* > DetailedCostModel::peaks() const
{
QMap< QModelIndex, TreeLeafItem* > peaks;
- QHash< QString, QPair<TreeLeafItem*,SnapshotItem*> >::const_iterator it = m_peaks.constBegin();
+ QHash< QByteArray, QPair<TreeLeafItem*,SnapshotItem*> >::const_iterator it = m_peaks.constBegin();
while (it != m_peaks.end()) {
int row = m_rows.indexOf(it->second);
Q_ASSERT(row >= 0);
@@ -327,7 +327,7 @@ QPair< TreeLeafItem*, SnapshotItem* > DetailedCostModel::itemForIndex(const QMod
if (idx.row() == 0) {
return QPair< TreeLeafItem*, SnapshotItem* >(0, 0);
}
- const QString needle = m_columns.at(idx.column() / 2);
+ const QByteArray needle = m_columns.at(idx.column() / 2);
for (int i = 1; i < 3 && idx.row() - i >= 0; ++i) {
SnapshotItem* snapshot = m_rows.at(idx.row() - i);
foreach(TreeLeafItem* n, m_nodes[snapshot]) {
diff --git a/visualizer/detailedcostmodel.h b/visualizer/detailedcostmodel.h
index c3c84c9..ecd99e2 100644
--- a/visualizer/detailedcostmodel.h
+++ b/visualizer/detailedcostmodel.h
@@ -105,13 +105,13 @@ public:
private:
const FileData* m_data;
// columns => label
- QList<QString> m_columns;
+ QList<QByteArray> m_columns;
// only to sort snapshots by number
QList<SnapshotItem*> m_rows;
// snapshot item => cost intensive nodes
QHash<SnapshotItem*, QList<TreeLeafItem*> > m_nodes;
// peaks: Label => TreeLeafItem,Snapshot
- QHash<QString, QPair<TreeLeafItem*,SnapshotItem*> > m_peaks;
+ QHash<QByteArray, QPair<TreeLeafItem*,SnapshotItem*> > m_peaks;
// selected item
QModelIndex m_selection;
int m_maxDatasetCount;
diff --git a/visualizer/dotgraphgenerator.cpp b/visualizer/dotgraphgenerator.cpp
index b67d78d..be5e7f1 100644
--- a/visualizer/dotgraphgenerator.cpp
+++ b/visualizer/dotgraphgenerator.cpp
@@ -128,7 +128,7 @@ GraphNode* buildGraph(const TreeLeafItem* item, QMultiHash<QString, GraphNode*>&
if (parent && item->children().isEmpty()) {
static QRegExp matchBT("in ([0-9]+) places, all below massif's threshold",
Qt::CaseSensitive, QRegExp::RegExp2);
- if (item->label().indexOf(matchBT) != -1) {
+ if (matchBT.indexIn(QString::fromLatin1(item->label())) != -1) {
parent->belowThresholdCost += item->cost();
parent->belowThresholdCount += matchBT.cap(1).toInt();
}