diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2010-02-26 13:13:41 (GMT) |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2010-02-26 13:15:24 (GMT) |
commit | 7ce54e9cc4b35d16c32f4dfc5875038797731f2f (patch) | |
tree | d5c7e0a656e6bdb1a040d06deed2132cad5c2551 /src/corelib/kernel | |
parent | 68c02d299f0e423582d34169b3d4597d179a53a2 (diff) | |
download | Qt-7ce54e9cc4b35d16c32f4dfc5875038797731f2f.zip Qt-7ce54e9cc4b35d16c32f4dfc5875038797731f2f.tar.gz Qt-7ce54e9cc4b35d16c32f4dfc5875038797731f2f.tar.bz2 |
Improve lookup speed of QMetaType::type() for normalized types
Two improvements are made:
1) Store the length of the built-in types to avoid calling
strcmp() when there's no way the types will match; and
2) Speculate on the input already being normalized.
When the type name is already in normalized form (which we
believe to be the common case), normalizing is wasteful
(allocating a bytearray that's going to contain exactly the
same string as the original input).
Use the same pattern as used in QObject::connect(), which
speculates on the signature already being normalized; only
if the lookup fails, the signature is normalized and looked
up again.
For the QMetaType::builtinTypes benchmark, this improves
performance by roughly 4x.
For the QMetaType::builtinTypesNotNormalized benchmark, the
performance is half of that before, because the lookup is
done twice. But we choose to optimize for the already-normalized
case. This makes a big difference in the QtScript QObject
bindings, for example.
Reviewed-by: Harald Fernengel
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 197 |
1 files changed, 103 insertions, 94 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 870baab..bfc3e28 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -223,100 +223,103 @@ QT_BEGIN_NAMESPACE \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue() */ +#define QT_ADD_STATIC_METATYPE(STR, TP) \ + { STR, sizeof(STR) - 1, TP } + /* Note: these MUST be in the order of the enums */ -static const struct { const char * typeName; int type; } types[] = { +static const struct { const char * typeName; int typeNameLength; int type; } types[] = { /* All Core types */ - {"void", QMetaType::Void}, - {"bool", QMetaType::Bool}, - {"int", QMetaType::Int}, - {"uint", QMetaType::UInt}, - {"qlonglong", QMetaType::LongLong}, - {"qulonglong", QMetaType::ULongLong}, - {"double", QMetaType::Double}, - {"QChar", QMetaType::QChar}, - {"QVariantMap", QMetaType::QVariantMap}, - {"QVariantList", QMetaType::QVariantList}, - {"QString", QMetaType::QString}, - {"QStringList", QMetaType::QStringList}, - {"QByteArray", QMetaType::QByteArray}, - {"QBitArray", QMetaType::QBitArray}, - {"QDate", QMetaType::QDate}, - {"QTime", QMetaType::QTime}, - {"QDateTime", QMetaType::QDateTime}, - {"QUrl", QMetaType::QUrl}, - {"QLocale", QMetaType::QLocale}, - {"QRect", QMetaType::QRect}, - {"QRectF", QMetaType::QRectF}, - {"QSize", QMetaType::QSize}, - {"QSizeF", QMetaType::QSizeF}, - {"QLine", QMetaType::QLine}, - {"QLineF", QMetaType::QLineF}, - {"QPoint", QMetaType::QPoint}, - {"QPointF", QMetaType::QPointF}, - {"QRegExp", QMetaType::QRegExp}, - {"QVariantHash", QMetaType::QVariantHash}, + QT_ADD_STATIC_METATYPE("void", QMetaType::Void), + QT_ADD_STATIC_METATYPE("bool", QMetaType::Bool), + QT_ADD_STATIC_METATYPE("int", QMetaType::Int), + QT_ADD_STATIC_METATYPE("uint", QMetaType::UInt), + QT_ADD_STATIC_METATYPE("qlonglong", QMetaType::LongLong), + QT_ADD_STATIC_METATYPE("qulonglong", QMetaType::ULongLong), + QT_ADD_STATIC_METATYPE("double", QMetaType::Double), + QT_ADD_STATIC_METATYPE("QChar", QMetaType::QChar), + QT_ADD_STATIC_METATYPE("QVariantMap", QMetaType::QVariantMap), + QT_ADD_STATIC_METATYPE("QVariantList", QMetaType::QVariantList), + QT_ADD_STATIC_METATYPE("QString", QMetaType::QString), + QT_ADD_STATIC_METATYPE("QStringList", QMetaType::QStringList), + QT_ADD_STATIC_METATYPE("QByteArray", QMetaType::QByteArray), + QT_ADD_STATIC_METATYPE("QBitArray", QMetaType::QBitArray), + QT_ADD_STATIC_METATYPE("QDate", QMetaType::QDate), + QT_ADD_STATIC_METATYPE("QTime", QMetaType::QTime), + QT_ADD_STATIC_METATYPE("QDateTime", QMetaType::QDateTime), + QT_ADD_STATIC_METATYPE("QUrl", QMetaType::QUrl), + QT_ADD_STATIC_METATYPE("QLocale", QMetaType::QLocale), + QT_ADD_STATIC_METATYPE("QRect", QMetaType::QRect), + QT_ADD_STATIC_METATYPE("QRectF", QMetaType::QRectF), + QT_ADD_STATIC_METATYPE("QSize", QMetaType::QSize), + QT_ADD_STATIC_METATYPE("QSizeF", QMetaType::QSizeF), + QT_ADD_STATIC_METATYPE("QLine", QMetaType::QLine), + QT_ADD_STATIC_METATYPE("QLineF", QMetaType::QLineF), + QT_ADD_STATIC_METATYPE("QPoint", QMetaType::QPoint), + QT_ADD_STATIC_METATYPE("QPointF", QMetaType::QPointF), + QT_ADD_STATIC_METATYPE("QRegExp", QMetaType::QRegExp), + QT_ADD_STATIC_METATYPE("QVariantHash", QMetaType::QVariantHash), /* All GUI types */ - {"QColorGroup", 63}, - {"QFont", QMetaType::QFont}, - {"QPixmap", QMetaType::QPixmap}, - {"QBrush", QMetaType::QBrush}, - {"QColor", QMetaType::QColor}, - {"QPalette", QMetaType::QPalette}, - {"QIcon", QMetaType::QIcon}, - {"QImage", QMetaType::QImage}, - {"QPolygon", QMetaType::QPolygon}, - {"QRegion", QMetaType::QRegion}, - {"QBitmap", QMetaType::QBitmap}, - {"QCursor", QMetaType::QCursor}, - {"QSizePolicy", QMetaType::QSizePolicy}, - {"QKeySequence", QMetaType::QKeySequence}, - {"QPen", QMetaType::QPen}, - {"QTextLength", QMetaType::QTextLength}, - {"QTextFormat", QMetaType::QTextFormat}, - {"QMatrix", QMetaType::QMatrix}, - {"QTransform", QMetaType::QTransform}, - {"QMatrix4x4", QMetaType::QMatrix4x4}, - {"QVector2D", QMetaType::QVector2D}, - {"QVector3D", QMetaType::QVector3D}, - {"QVector4D", QMetaType::QVector4D}, - {"QQuaternion", QMetaType::QQuaternion}, + QT_ADD_STATIC_METATYPE("QColorGroup", 63), + QT_ADD_STATIC_METATYPE("QFont", QMetaType::QFont), + QT_ADD_STATIC_METATYPE("QPixmap", QMetaType::QPixmap), + QT_ADD_STATIC_METATYPE("QBrush", QMetaType::QBrush), + QT_ADD_STATIC_METATYPE("QColor", QMetaType::QColor), + QT_ADD_STATIC_METATYPE("QPalette", QMetaType::QPalette), + QT_ADD_STATIC_METATYPE("QIcon", QMetaType::QIcon), + QT_ADD_STATIC_METATYPE("QImage", QMetaType::QImage), + QT_ADD_STATIC_METATYPE("QPolygon", QMetaType::QPolygon), + QT_ADD_STATIC_METATYPE("QRegion", QMetaType::QRegion), + QT_ADD_STATIC_METATYPE("QBitmap", QMetaType::QBitmap), + QT_ADD_STATIC_METATYPE("QCursor", QMetaType::QCursor), + QT_ADD_STATIC_METATYPE("QSizePolicy", QMetaType::QSizePolicy), + QT_ADD_STATIC_METATYPE("QKeySequence", QMetaType::QKeySequence), + QT_ADD_STATIC_METATYPE("QPen", QMetaType::QPen), + QT_ADD_STATIC_METATYPE("QTextLength", QMetaType::QTextLength), + QT_ADD_STATIC_METATYPE("QTextFormat", QMetaType::QTextFormat), + QT_ADD_STATIC_METATYPE("QMatrix", QMetaType::QMatrix), + QT_ADD_STATIC_METATYPE("QTransform", QMetaType::QTransform), + QT_ADD_STATIC_METATYPE("QMatrix4x4", QMetaType::QMatrix4x4), + QT_ADD_STATIC_METATYPE("QVector2D", QMetaType::QVector2D), + QT_ADD_STATIC_METATYPE("QVector3D", QMetaType::QVector3D), + QT_ADD_STATIC_METATYPE("QVector4D", QMetaType::QVector4D), + QT_ADD_STATIC_METATYPE("QQuaternion", QMetaType::QQuaternion), /* All Metatype builtins */ - {"void*", QMetaType::VoidStar}, - {"long", QMetaType::Long}, - {"short", QMetaType::Short}, - {"char", QMetaType::Char}, - {"ulong", QMetaType::ULong}, - {"ushort", QMetaType::UShort}, - {"uchar", QMetaType::UChar}, - {"float", QMetaType::Float}, - {"QObject*", QMetaType::QObjectStar}, - {"QWidget*", QMetaType::QWidgetStar}, + QT_ADD_STATIC_METATYPE("void*", QMetaType::VoidStar), + QT_ADD_STATIC_METATYPE("long", QMetaType::Long), + QT_ADD_STATIC_METATYPE("short", QMetaType::Short), + QT_ADD_STATIC_METATYPE("char", QMetaType::Char), + QT_ADD_STATIC_METATYPE("ulong", QMetaType::ULong), + QT_ADD_STATIC_METATYPE("ushort", QMetaType::UShort), + QT_ADD_STATIC_METATYPE("uchar", QMetaType::UChar), + QT_ADD_STATIC_METATYPE("float", QMetaType::Float), + QT_ADD_STATIC_METATYPE("QObject*", QMetaType::QObjectStar), + QT_ADD_STATIC_METATYPE("QWidget*", QMetaType::QWidgetStar), /* Type aliases - order doesn't matter */ - {"unsigned long", QMetaType::ULong}, - {"unsigned int", QMetaType::UInt}, - {"unsigned short", QMetaType::UShort}, - {"unsigned char", QMetaType::UChar}, - {"long long", QMetaType::LongLong}, - {"unsigned long long", QMetaType::ULongLong}, - {"qint8", QMetaType::Char}, - {"quint8", QMetaType::UChar}, - {"qint16", QMetaType::Short}, - {"quint16", QMetaType::UShort}, - {"qint32", QMetaType::Int}, - {"quint32", QMetaType::UInt}, - {"qint64", QMetaType::LongLong}, - {"quint64", QMetaType::ULongLong}, - {"QList<QVariant>", QMetaType::QVariantList}, - {"QMap<QString,QVariant>", QMetaType::QVariantMap}, - {"QHash<QString,QVariant>", QMetaType::QVariantHash}, + QT_ADD_STATIC_METATYPE("unsigned long", QMetaType::ULong), + QT_ADD_STATIC_METATYPE("unsigned int", QMetaType::UInt), + QT_ADD_STATIC_METATYPE("unsigned short", QMetaType::UShort), + QT_ADD_STATIC_METATYPE("unsigned char", QMetaType::UChar), + QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong), + QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong), + QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char), + QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar), + QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short), + QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort), + QT_ADD_STATIC_METATYPE("qint32", QMetaType::Int), + QT_ADD_STATIC_METATYPE("quint32", QMetaType::UInt), + QT_ADD_STATIC_METATYPE("qint64", QMetaType::LongLong), + QT_ADD_STATIC_METATYPE("quint64", QMetaType::ULongLong), + QT_ADD_STATIC_METATYPE("QList<QVariant>", QMetaType::QVariantList), + QT_ADD_STATIC_METATYPE("QMap<QString,QVariant>", QMetaType::QVariantMap), + QT_ADD_STATIC_METATYPE("QHash<QString,QVariant>", QMetaType::QVariantHash), // let QMetaTypeId2 figure out the type at compile time - {"qreal", QMetaTypeId2<qreal>::MetaType}, + QT_ADD_STATIC_METATYPE("qreal", QMetaTypeId2<qreal>::MetaType), - {0, QMetaType::Void} + {0, 0, QMetaType::Void} }; struct QMetaTypeGuiHelper @@ -409,19 +412,24 @@ const char *QMetaType::typeName(int type) /*! \internal Same as QMetaType::type(), but doesn't lock the mutex. */ -static int qMetaTypeType_unlocked(const QByteArray &typeName) +static int qMetaTypeType_unlocked(const char *typeName) { + int length = qstrlen(typeName); int i = 0; - while (types[i].typeName && strcmp(typeName.constData(), types[i].typeName)) + while (types[i].typeName && ((length != types[i].typeNameLength) + || strcmp(typeName, types[i].typeName))) { ++i; + } if (!types[i].type) { const QVector<QCustomTypeInfo> * const ct = customTypes(); if (!ct) return 0; for (int v = 0; v < ct->count(); ++v) { - if (ct->at(v).typeName == typeName) + if ((length == ct->at(v).typeName.size()) + && !strcmp(typeName, ct->at(v).typeName.constData())) { return v + QMetaType::User; + } } } return types[i].type; @@ -447,7 +455,7 @@ int QMetaType::registerType(const char *typeName, Destructor destructor, #endif QWriteLocker locker(customTypesLock()); - int idx = qMetaTypeType_unlocked(normalizedTypeName); + int idx = qMetaTypeType_unlocked(normalizedTypeName.constData()); if (!idx) { QCustomTypeInfo inf; @@ -514,14 +522,15 @@ bool QMetaType::isRegistered(int type) */ int QMetaType::type(const char *typeName) { -#ifdef QT_NO_QOBJECT - const NS(QByteArray) normalizedTypeName = typeName; -#else - const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); -#endif - QReadLocker locker(customTypesLock()); - return qMetaTypeType_unlocked(normalizedTypeName); + int type = qMetaTypeType_unlocked(typeName); +#ifndef QT_NO_QOBJECT + if (!type) { + const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); + type = qMetaTypeType_unlocked(normalizedTypeName.constData()); + } +#endif + return type; } #ifndef QT_NO_DATASTREAM |