Commit 3ae66fab authored by Maks Orlovich's avatar Maks Orlovich

Reduce memory usage by roughly a 1/3rd, by:

1. Reove a redudndant copy of the file path in CachedTag
2. Try to get multiple copies of the same text to use the same
underlying data object more often.
3. Don't let QString get too pre-allocation happy.

svn path=/trunk/kdemultimedia/juk/; revision=262331
parent 8cc19046
......@@ -14,7 +14,7 @@ juk_SOURCES = directorylistbase.ui genrelisteditorbase.ui \
searchplaylist.cpp musicbrainzquery.cpp mediafiles.cpp viewmode.cpp \
advancedsearchdialog.cpp historyplaylist.cpp trackpickerdialogbase.ui \
musicbrainzitem.cpp trackpickerdialog.cpp filerenamerconfigdlgwidget.ui \
filerenamerconfigdlg.cpp
filerenamerconfigdlg.cpp stringshare.cpp
tagguessertest_SOURCES = tagguessertest.cpp tagguesser.cpp
......
......@@ -119,6 +119,7 @@ void Cache::load()
QString fileName;
s >> fileName;
fileName.squeeze();
CachedTag *t = new CachedTag(fileName);
s >> *t;
......
......@@ -21,6 +21,7 @@
#include "cachedtag.h"
#include "cache.h"
#include "stringshare.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......@@ -184,6 +185,7 @@ bool CachedTag::current() const
QDataStream &CachedTag::read(QDataStream &s)
{
QString dummy;
/// TODO: Use Q_UINT32 in place of all integers.
#if 0 /// TODO: This should be included the next time that the cache format changes
s >> m_tagExists
......@@ -206,9 +208,19 @@ QDataStream &CachedTag::read(QDataStream &s)
>> m_tagLengthString
>> m_tagSeconds
>> m_fileName
>> dummy //Was filename, not really needed - the base has it already
>> m_modificationTime;
//Try to reduce memory usage: share tags that frequently repeat, squeeze others
m_tagTrack.squeeze();
m_tagComment = StringShare::tryShare(m_tagComment);
m_tagArtist = StringShare::tryShare(m_tagArtist);
m_tagAlbum = StringShare::tryShare(m_tagAlbum);
m_tagTrackNumberString = StringShare::tryShare(m_tagTrackNumberString);
m_tagYearString = StringShare::tryShare(m_tagYearString);
m_tagBitrateString = StringShare::tryShare(m_tagBitrateString);
m_tagLengthString.squeeze();
return s;
}
......
......@@ -81,7 +81,6 @@ private:
bool m_tagExists;
QString m_fileName;
QDateTime m_modificationTime;
};
......
......@@ -17,6 +17,7 @@
#include "genre.h"
#include "genrelistlist.h"
#include "stringshare.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......@@ -29,7 +30,7 @@ Genre::Genre() :
}
Genre::Genre(const QString &name) :
m_name(name)
m_name(StringShare::tryShare(name))
{
m_ID3v1 = GenreListList::ID3v1List().findIndex(name);
if(m_ID3v1 < 0)
......@@ -37,7 +38,7 @@ Genre::Genre(const QString &name) :
}
Genre::Genre(const QString &name, int ID3v1) :
m_name(name),
m_name(StringShare::tryShare(name)),
m_ID3v1(ID3v1)
{
......@@ -60,7 +61,7 @@ QDataStream &operator>>(QDataStream &s, Genre &g)
s >> name >> n;
g.setName(name);
g.setName(StringShare::tryShare(name));
g.setID3v1(n);
return s;
......
......@@ -25,6 +25,7 @@
#include "collectionlist.h"
#include "trackpickerdialog.h"
#include "musicbrainzitem.h"
#include "stringshare.h"
////////////////////////////////////////////////////////////////////////////////
// PlaylistItem public methods
......@@ -309,7 +310,18 @@ void PlaylistItem::slotRefreshImpl()
m_data->setColumns(columns);
for(int i = 0; i < columns; i++) {
m_data->setLocal8BitLower(i, text(i).lower().local8Bit());
int id = i - offset;
if (id != TrackNumberColumn && id != LengthColumn)
{
//All columns other than track num and length need local-encoded data for sorting
QCString lower = text(i).lower().local8Bit();
//For some columns, we may be able to share some strings
if ((id == ArtistColumn) || (id == AlbumColumn) ||
(id == GenreColumn) || (id == YearColumn) ||
(id == CommentColumn))
lower = StringShare::tryShare(lower);
m_data->setLocal8BitLower(i, lower);
}
int newWidth = width(listView()->fontMetrics(), listView(), i);
m_data->setCachedWidth(i, newWidth);
if(newWidth != m_data->cachedWidth(i))
......@@ -399,6 +411,7 @@ void PlaylistItem::Data::refresh()
m_dataTag = Tag::createTag(m_fileInfo.filePath());
Q_ASSERT(m_dataTag);
m_absFileName = m_fileInfo.absFilePath();
m_fileInfo.refresh(); //Dump cached into we don't need
}
void PlaylistItem::Data::deleteUser()
......
......@@ -21,24 +21,8 @@
// private methods
////////////////////////////////////////////////////////////////////////////////
int StringHash::hash(QString key) const
{
uint h = 0;
uint g;
const QChar *p = key.unicode();
for(int i = 0; i < int(key.length()); i++) {
h = (h << 4) + p[i].cell();
if((g = h & 0xf0000000))
h ^= g >> 24;
h &= ~g;
}
int index = h;
if(index < 0)
index = -index;
return index % tableSize();
return hashString(key) % tableSize();
}
......@@ -75,6 +75,35 @@ private:
static const int m_tableSize = 5003;
};
inline char hashStringAccess(const QString& in, int index)
{
return in.unicode()[index].cell();
}
inline char hashStringAccess(const QCString& in, int index)
{
return in[index];
}
//Based on QGDict's hash functions, Copyright (C) 1992-2000 Trolltech AS
template<typename StringType>
inline int hashString(const StringType& string)
{
uint h = 0;
uint g;
for ( uint i = 0; i<string.length(); i++ )
{
h = (h<<4) + hashStringAccess(string, i);
if ( (g = h & 0xf0000000) )
h ^= g >> 24;
h &= ~g;
}
int index = h;
if (index < 0)
index = -index;
return index;
}
class StringHash : public Hash<QString>
{
public:
......
/***************************************************************************
stringshare.h - string memory usage optimization
-------------------
begin : Sat Oct 25 2003
copyright : (C) 2003 by Maksim Orlovich
email : maksim.orlovich@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "stringshare.h"
#include "stringhash.h"
const int SIZE = 5003;
StringShare::Data* StringShare::s_data = 0;
/**
We store the strings in two simple direct-mapped (i.e. no collision handling, just replace) hashes, which contain strings or null objects. This costs only 4 bytes per slot on 32-bit
archs, so with the default constant size we only really use 40K or so.
The end result is that many strings end up pointing to the same underlying data object,
instead of each one having its own little copy.
*/
struct StringShare::Data
{
QString qstringHash [SIZE];
QCString qcstringHash[SIZE];
};
StringShare::Data* StringShare::data()
{
if (!s_data)
s_data = new Data;
return s_data;
}
QString StringShare::tryShare(const QString& in)
{
int index = hashString(in) % SIZE;
Data* dat = data();
if (dat->qstringHash[index] == in) //Match
return dat->qstringHash[index];
else
{
//Else replace whatever was there before
dat->qstringHash[index] = in;
return in;
}
}
QCString StringShare::tryShare(const QCString& in)
{
int index = hashString(in) % SIZE;
Data* dat = data();
if (dat->qcstringHash[index] == in) //Match
return dat->qcstringHash[index];
else
{
//Else replace whatever was there before
dat->qcstringHash[index] = in;
return in;
}
}
/***************************************************************************
stringshare.h - string memory usage optimization
-------------------
begin : Sat Oct 25 2003
copyright : (C) 2003 by Maksim Orlovich
email : maksim.orlovich@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef STRING_SHARE_H
#define STRING_SHARE_H
#include <qstring.h>
/**
This class attempts to normalize repeated occurances of strings to use
the same shared object, if possible, by using a small hash
*/
class StringShare
{
struct Data;
public:
static QString tryShare(const QString& in);
static QCString tryShare(const QCString& in);
private:
static Data* data();
static Data* s_data;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment