Use file mapping in moc.
The change reduces heap allocations by using file mapping instead of
reading a whole file into memory just to create a slightly modified
copy of it.
For this small test case:
moc <<EOF
class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };
EOF
massif shows improvement from:
peak cost: "26,8 KB" heap "2,1 KB" heap extra "0 B" stacks
to:
peak cost: "11,3 KB" heap "2,2 KB" heap extra "0 B" stacks
In general, depending on source file high peak memory usage is reduced
from few to few hundreds KB, especially that the allocation used to
happen for each include file too.
Change-Id: I9c1c848be848444156af25a991b67161fb9d8b29
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
bb10
parent
8c77a7f77a
commit
053e8c41d7
|
|
@ -52,11 +52,12 @@ static QByteArray cleaned(const QByteArray &input)
|
|||
QByteArray result;
|
||||
result.reserve(input.size());
|
||||
const char *data = input.constData();
|
||||
const char *end = input.constData() + input.size();
|
||||
char *output = result.data();
|
||||
|
||||
int newlines = 0;
|
||||
while (*data) {
|
||||
while (*data && is_space(*data))
|
||||
while (data != end) {
|
||||
while (data != end && is_space(*data))
|
||||
++data;
|
||||
bool takeLine = (*data == '#');
|
||||
if (*data == '%' && *(data+1) == ':') {
|
||||
|
|
@ -66,15 +67,15 @@ static QByteArray cleaned(const QByteArray &input)
|
|||
if (takeLine) {
|
||||
*output = '#';
|
||||
++output;
|
||||
do ++data; while (*data && is_space(*data));
|
||||
do ++data; while (data != end && is_space(*data));
|
||||
}
|
||||
while (*data) {
|
||||
while (data != end) {
|
||||
// handle \\\n, \\\r\n and \\\r
|
||||
if (*data == '\\') {
|
||||
if (*(data + 1) == '\r') {
|
||||
++data;
|
||||
}
|
||||
if (*data && (*(data + 1) == '\n' || (*data) == '\r')) {
|
||||
if (data != end && (*(data + 1) == '\n' || (*data) == '\r')) {
|
||||
++newlines;
|
||||
data += 1;
|
||||
if (*data != '\r')
|
||||
|
|
@ -964,6 +965,13 @@ int Preprocessor::evaluateCondition()
|
|||
return expression.value();
|
||||
}
|
||||
|
||||
static QByteArray readOrMapFile(QFile *file)
|
||||
{
|
||||
const qint64 size = file->size();
|
||||
char *rawInput = reinterpret_cast<char*>(file->map(0, size));
|
||||
return rawInput ? QByteArray::fromRawData(rawInput, size) : file->readAll();
|
||||
}
|
||||
|
||||
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
||||
{
|
||||
currentFilenames.push(filename);
|
||||
|
|
@ -1020,7 +1028,8 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
|||
if (!file.open(QFile::ReadOnly))
|
||||
continue;
|
||||
|
||||
QByteArray input = file.readAll();
|
||||
QByteArray input = readOrMapFile(&file);
|
||||
|
||||
file.close();
|
||||
if (input.isEmpty())
|
||||
continue;
|
||||
|
|
@ -1157,9 +1166,10 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
|||
currentFilenames.pop();
|
||||
}
|
||||
|
||||
Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
|
||||
Symbols Preprocessor::preprocessed(const QByteArray &filename, QFile *file)
|
||||
{
|
||||
QByteArray input = file->readAll();
|
||||
QByteArray input = readOrMapFile(file);
|
||||
|
||||
if (input.isEmpty())
|
||||
return symbols;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ typedef SubArray MacroName;
|
|||
#endif
|
||||
typedef QHash<MacroName, Macro> Macros;
|
||||
|
||||
class QIODevice;
|
||||
class QFile;
|
||||
|
||||
class Preprocessor : public Parser
|
||||
{
|
||||
|
|
@ -67,7 +67,7 @@ public:
|
|||
QList<QByteArray> frameworks;
|
||||
QSet<QByteArray> preprocessedIncludes;
|
||||
Macros macros;
|
||||
Symbols preprocessed(const QByteArray &filename, QIODevice *device);
|
||||
Symbols preprocessed(const QByteArray &filename, QFile *device);
|
||||
|
||||
void parseDefineArguments(Macro *m);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue