diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index 56d6cf14c559702d07ae9c76f66141e80bd484cf..e4620a282a2b41ec10ba23a93a96a3ad3571c892 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -134,22 +134,12 @@ void QQmlProfilerData::toByteArrays(QList<QByteArray> &messages) const
     }
 }
 
-void QQmlProfilerService::animationTimerCallback(qint64 delta)
-{
-    Q_QML_PROFILE(animationFrame(delta));
-}
-
 QQmlProfilerService::QQmlProfilerService()
     : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1)
 {
     m_timer.start();
 
     QMutexLocker lock(configMutex());
-    // TODO: This is problematic as the service could be enabled at a later point in time. In that
-    //       case we might miss the callback registration.
-    if (state() == Enabled)
-        QUnifiedTimer::instance()->registerProfilerCallback(&animationTimerCallback);
-
     // If there is no debug server it doesn't matter as we'll never get enabled anyway.
     if (QQmlDebugServer::instance() != 0)
         moveToThread(QQmlDebugServer::instance()->thread());
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 4549814a02549e0c1d73b57bab265d2036c196c8..a5d85a76e63378786e6a12b3b06f71972fa8c500 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -58,8 +58,6 @@
 #include "qqmlabstractprofileradapter_p.h"
 
 #include <private/qqmlboundsignal_p.h>
-// this contains QUnifiedTimer
-#include <private/qabstractanimation_p.h>
 #include <private/qv4function_p.h>
 
 #include <QtCore/qelapsedtimer.h>
@@ -78,11 +76,6 @@
 #define Q_QML_PROFILE(Method)\
     Q_QML_PROFILE_IF_ENABLED(QQmlProfilerService::Method)
 
-#define Q_QML_SG_PROFILE2(Type1, Type2, Params)\
-    Q_QML_PROFILE_IF_ENABLED((QQmlProfilerService::sceneGraphFrame<Type1, Type2> Params))
-
-#define Q_QML_SG_PROFILE1(Type, Params) Q_QML_SG_PROFILE2(Type, Type, Params)
-
 QT_BEGIN_NAMESPACE
 
 // This struct is somewhat dangerous to use:
@@ -183,55 +176,6 @@ public:
     void startProfiling(QQmlEngine *engine);
     void stopProfiling(QQmlEngine *engine);
 
-    template<EventType DetailType>
-    static void addEvent()
-    {
-        m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << Event,
-                                                  1 << DetailType));
-    }
-
-    static void animationFrame(qint64 delta)
-    {
-        int animCount = QUnifiedTimer::instance()->runningAnimationCount();
-
-        if (animCount > 0 && delta > 0) {
-            m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << Event,
-                                                      1 << AnimationFrame, QString(), 0, 0,
-                                                      1000 / (int)delta /* trim fps to integer */,
-                                                      animCount));
-        }
-    }
-
-    template<SceneGraphFrameType FrameType1, SceneGraphFrameType FrameType2>
-    static void sceneGraphFrame(qint64 value1, qint64 value2 = -1, qint64 value3 = -1,
-                                qint64 value4 = -1, qint64 value5 = -1)
-    {
-        m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << SceneGraphFrame,
-                                                  1 << FrameType1 | 1 << FrameType2,
-                                                  value1, value2, value3, value4, value5));
-    }
-
-    template<PixmapEventType PixmapState>
-    static void pixmapStateChanged(const QUrl &url)
-    {
-        m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << PixmapCacheEvent,
-                                                  1 << PixmapState, url));
-    }
-
-    static void pixmapLoadingFinished(const QUrl &url, const QSize &size)
-    {
-        m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << PixmapCacheEvent,
-                (1 << PixmapLoadingFinished) | ((size.width() > 0 && size.height() > 0) ? (1 << PixmapSizeKnown) : 0),
-                url, size.width(), size.height()));
-    }
-
-    template<PixmapEventType CountType>
-    static void pixmapCountChanged(const QUrl &url, int count)
-    {
-        m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << PixmapCacheEvent,
-                                                  1 << CountType, url, 0, 0, 0, count));
-    }
-
     qint64 timestamp() {return m_timer.nsecsElapsed();}
 
     QQmlProfilerService();
@@ -307,8 +251,6 @@ private:
         m_data.append(message);
     }
 
-    static void animationTimerCallback(qint64 delta);
-
 public:
     static bool enabled;
 private:
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 1a3d2259952b5e3173f72fa16c4e0e401278f5d7..5c9ecb93dd3ef1912e15c149fbe49f65b522dcf7 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -46,7 +46,7 @@
 #include "qquickitem_p.h"
 #include "qquickitemchangelistener_p.h"
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 #include <private/qqmlinspectorservice_p.h>
 #include <private/qqmlmemoryprofiler_p.h>
 
@@ -603,7 +603,7 @@ void QQuickView::resizeEvent(QResizeEvent *e)
 /*! \reimp */
 void QQuickView::keyPressEvent(QKeyEvent *e)
 {
-    Q_QML_PROFILE(addEvent<QQmlProfilerService::Key>());
+    Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
 
     QQuickWindow::keyPressEvent(e);
 }
@@ -611,7 +611,7 @@ void QQuickView::keyPressEvent(QKeyEvent *e)
 /*! \reimp */
 void QQuickView::keyReleaseEvent(QKeyEvent *e)
 {
-    Q_QML_PROFILE(addEvent<QQmlProfilerService::Key>());
+    Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
 
     QQuickWindow::keyReleaseEvent(e);
 }
@@ -619,7 +619,7 @@ void QQuickView::keyReleaseEvent(QKeyEvent *e)
 /*! \reimp */
 void QQuickView::mouseMoveEvent(QMouseEvent *e)
 {
-    Q_QML_PROFILE(addEvent<QQmlProfilerService::Mouse>());
+    Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     QQuickWindow::mouseMoveEvent(e);
 }
@@ -627,7 +627,7 @@ void QQuickView::mouseMoveEvent(QMouseEvent *e)
 /*! \reimp */
 void QQuickView::mousePressEvent(QMouseEvent *e)
 {
-    Q_QML_PROFILE(addEvent<QQmlProfilerService::Mouse>());
+    Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     QQuickWindow::mousePressEvent(e);
 }
@@ -635,7 +635,7 @@ void QQuickView::mousePressEvent(QMouseEvent *e)
 /*! \reimp */
 void QQuickView::mouseReleaseEvent(QMouseEvent *e)
 {
-    Q_QML_PROFILE(addEvent<QQmlProfilerService::Mouse>());
+    Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     QQuickWindow::mouseReleaseEvent(e);
 }
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index ee5034c10872432d29a5692bdd5041dd917210c4..9d2a0b0f75dd19ccf6f367e81f87854562f95ede 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -49,6 +49,7 @@
 #include <private/qqmldebugstatesdelegate_p.h>
 #include <private/qqmlbinding_p.h>
 #include <private/qqmlcontext_p.h>
+#include <private/qquickprofiler_p.h>
 #include <private/qquickapplication_p.h>
 #include <QtQuick/private/qquickpropertychanges_p.h>
 #include <QtQuick/private/qquickstate_p.h>
@@ -189,9 +190,10 @@ void QQmlQtQuick2Module::defineModule()
 
     QQuickValueTypes::registerValueTypes();
 
-    if (QQmlEngineDebugService::isDebuggingEnabled()) {
+    if (QQmlDebugService::isDebuggingEnabled()) {
         QQmlEngineDebugService::instance()->setStatesDelegate(
                     new QQmlQtQuick2DebugStatesDelegate);
+        QQuickProfiler::initialize();
     }
 }
 
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 8dfa0d2c2c6feb868bb2d418c11acfa59dba87b1..f121e1652353ce94e54e2fdd8446fc4c703eab8a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -48,12 +48,13 @@
 #include <qmath.h>
 
 #include <QtCore/QElapsedTimer>
+#include <QtCore/QtNumeric>
 
 #include <QtGui/QGuiApplication>
 #include <QtGui/QOpenGLFramebufferObject>
 #include <QtGui/QOpenGLVertexArrayObject>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 #include <algorithm>
 
@@ -133,7 +134,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
         return shader;
 
 #ifndef QSG_NO_RENDER_TIMING
-    if (qsg_render_timing  || QQmlProfilerService::enabled)
+    if (qsg_render_timing  || QQuickProfiler::enabled)
         qsg_renderer_timer.start();
 #endif
 
@@ -176,7 +177,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
     if (qsg_render_timing)
         qDebug("   - compiling material: %dms", (int) qsg_renderer_timer.elapsed());
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphContextFrame, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphContextFrame, (
             qsg_renderer_timer.nsecsElapsed()));
 #endif
 
@@ -192,7 +193,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
         return shader;
 
 #ifndef QSG_NO_RENDER_TIMING
-    if (qsg_render_timing  || QQmlProfilerService::enabled)
+    if (qsg_render_timing  || QQuickProfiler::enabled)
         qsg_renderer_timer.start();
 #endif
 
@@ -212,7 +213,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
     if (qsg_render_timing)
         qDebug("   - compiling material: %dms", (int) qsg_renderer_timer.elapsed());
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphContextFrame, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphContextFrame, (
             qsg_renderer_timer.nsecsElapsed()));
 #endif
 
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 047891e17c507aa43d50b5003396b980f0b28ace..cc8793c0cf8f18df52aad0d1bb0585b3f74a5e34 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -54,7 +54,7 @@
 
 #include <qdatetime.h>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -227,7 +227,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
 
 
 #ifndef QSG_NO_RENDER_TIMING
-    bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
     if (profileFrames)
         frameTimer.start();
     qint64 bindTime = 0;
@@ -287,7 +287,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
                int(renderTime / 1000000));
     }
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphRendererFrame, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRendererFrame, (
             preprocessTime,
             updatePassTime - preprocessTime,
             bindTime - updatePassTime,
@@ -375,7 +375,7 @@ void QSGRenderer::preprocess()
     }
 
 #ifndef QSG_NO_RENDER_TIMING
-    bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
     if (profileFrames)
         preprocessTime = frameTimer.nsecsElapsed();
 #endif
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index aa678b34a6d69038bcb46deeda78e9f1cbb12626..17f4ba1243b8358bc4a5467f0b90c07d0ca490e8 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -48,7 +48,7 @@
 #include <QtGui/qguiapplication.h>
 #include <qdir.h>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 #include <QElapsedTimer>
 
 QT_BEGIN_NAMESPACE
@@ -164,7 +164,7 @@ void QSGDistanceFieldGlyphCache::update()
         return;
 
 #ifndef QSG_NO_RENDER_TIMING
-    bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
     if (profileFrames)
         qsg_render_timer.start();
 #endif
@@ -196,7 +196,7 @@ void QSGDistanceFieldGlyphCache::update()
                (int) qsg_render_timer.elapsed());
 
     }
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphAdaptationLayerFrame, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphAdaptationLayerFrame, (
             count,
             renderTime,
             qsg_render_timer.nsecsElapsed() - renderTime));
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 7b6e6d55eecd26a78c6b61475068ea045f9c1197..4e8fa67869f896813b47f3edc2df527a13bcc65c 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -57,7 +57,7 @@
 #include <QtQuick/QQuickWindow>
 #include <QtQuick/private/qquickwindow_p.h>
 #include <QtQuick/private/qsgcontext_p.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -304,7 +304,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
 
     qint64 renderTime = 0, syncTime = 0;
     QElapsedTimer renderTimer;
-    bool profileFrames = qsg_render_timing()  || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing()  || QQuickProfiler::enabled;
     if (profileFrames)
         renderTimer.start();
 
@@ -343,7 +343,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
         lastFrameTime = QTime::currentTime();
     }
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphRenderLoopFrame, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRenderLoopFrame, (
             syncTime,
             renderTime,
             swapTime));
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 7cc4293f6cc89dcaa3ff52385bcbcfea109b944a..ffc6d31aa70a5d34829cd166dcf1197fefe03d3d 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -58,7 +58,7 @@
 #include "qsgthreadedrenderloop_p.h"
 #include <private/qquickanimatorcontroller_p.h>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 /*
    Overall design:
@@ -539,7 +539,7 @@ void QSGRenderThread::sync()
 void QSGRenderThread::syncAndRender()
 {
 #ifndef QSG_NO_RENDER_TIMING
-    bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
     if (profileFrames) {
         sinceLastTime = threadTimer.nsecsElapsed();
         threadTimer.start();
@@ -609,7 +609,7 @@ void QSGRenderThread::syncAndRender()
                    int((renderTime - syncTime)/1000000),
                    int(threadTimer.elapsed() - renderTime/1000000));
 
-        Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphRenderLoopFrame, (
+        Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphRenderLoopFrame, (
                 syncTime,
                 renderTime - syncTime,
                 threadTimer.nsecsElapsed() - renderTime));
@@ -1081,7 +1081,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
     qint64 polishTime = 0;
     qint64 waitTime = 0;
     qint64 syncTime = 0;
-    bool profileFrames = qsg_render_timing  || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing  || QQuickProfiler::enabled;
     if (profileFrames)
         timer.start();
 #endif
@@ -1140,7 +1140,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
                int((syncTime - waitTime)/1000000),
                int((timer.nsecsElapsed() - syncTime)/1000000));
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphPolishAndSync, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphPolishAndSync, (
             polishTime,
             waitTime - polishTime,
             syncTime - waitTime,
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 63e3e958f6111cf388cf009dca0453344602f5b3..995d80bb826231e01521c777c4c34c41913cdfe8 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -51,7 +51,7 @@
 
 #include <QtQuick/QQuickWindow>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -69,7 +69,7 @@ static QElapsedTimer qsg_debug_timer;
 #ifndef QSG_NO_RENDER_TIMING
 static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty();
 static QElapsedTimer qsg_render_timer;
-#define QSG_RENDER_TIMING_SAMPLE(sampleName) qint64 sampleName = 0; if (qsg_render_timing || QQmlProfilerService::enabled) sampleName = qsg_render_timer.nsecsElapsed()
+#define QSG_RENDER_TIMING_SAMPLE(sampleName) qint64 sampleName = 0; if (qsg_render_timing || QQuickProfiler::enabled) sampleName = qsg_render_timer.nsecsElapsed()
 #else
 #define QSG_RENDER_TIMING_SAMPLE(sampleName)
 #endif
@@ -202,7 +202,7 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
                    int((time_current - time_created)/1000000),
                    int((qsg_render_timer.nsecsElapsed() - time_current)/1000000));
         }
-        Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphWindowsRenderShow, (
+        Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphWindowsRenderShow, (
                 time_created - time_start,
                 time_current - time_created,
                 qsg_render_timer.nsecsElapsed() - time_current));
@@ -404,7 +404,7 @@ void QSGWindowsRenderLoop::render()
             qDebug("WindowsRenderLoop: animations=%d ms",
                    int((qsg_render_timer.nsecsElapsed() - time_start)/1000000));
         }
-        Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphWindowsAnimations, (
+        Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphWindowsAnimations, (
                 qsg_render_timer.nsecsElapsed() - time_start));
 #endif
 
@@ -468,8 +468,8 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
                    int((time_swapped - time_rendered)/1000000));
         }
 
-        Q_QML_SG_PROFILE2(QQmlProfilerService::SceneGraphWindowsPolishFrame,
-                          QQmlProfilerService::SceneGraphRenderLoopFrame, (
+        Q_QUICK_SG_PROFILE2(QQuickProfiler::SceneGraphWindowsPolishFrame,
+                            QQuickProfiler::SceneGraphRenderLoopFrame, (
                 time_synced - time_polished,
                 time_rendered - time_synced,
                 time_swapped - time_rendered,
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index e39949253fac3867b55e8914771f84fc6a12835a..fe659c9add9ddaa11710bb256bbbdcd42cb9e36c 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -52,7 +52,7 @@
 
 #include <private/qsgtexture_p.h>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -374,7 +374,7 @@ bool Atlas::bind(QSGTexture::Filtering filtering)
     for (int i=0; i<m_pending_uploads.size(); ++i) {
 
 #ifndef QSG_NO_RENDER_TIMING
-        bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+        bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
         if (profileFrames)
             qsg_renderer_timer.start();
 #endif
@@ -394,7 +394,7 @@ bool Atlas::bind(QSGTexture::Filtering filtering)
                    (int) (qsg_renderer_timer.elapsed()));
         }
 
-        Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphTexturePrepare, (
+        Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTexturePrepare, (
                 0,  // bind (not relevant)
                 0,  // convert (not relevant)
                 0,  // swizzle (not relevant)
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 9620e48588fdb27d65e55d61467568f598ad2e5a..3bbcb0c11235a0e5ffb09882cca40b9f1afff0c1 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -45,7 +45,7 @@
 #include <qopenglfunctions.h>
 #include <QtQuick/private/qsgcontext_p.h>
 #include <qthread.h>
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 #include <private/qqmlglobal_p.h>
 #include <QtGui/qguiapplication.h>
 #include <QtGui/qpa/qplatformnativeinterface.h>
@@ -613,7 +613,7 @@ void QSGPlainTexture::bind()
     m_dirty_texture = false;
 
 #ifndef QSG_NO_RENDER_TIMING
-    bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled;
+    bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
     if (profileFrames)
         qsg_renderer_timer.start();
 #endif
@@ -628,7 +628,7 @@ void QSGPlainTexture::bind()
                        m_texture_size.width(),
                        m_texture_size.height());
             }
-            Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphTextureDeletion, (
+            Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTextureDeletion, (
                     qsg_renderer_timer.nsecsElapsed()));
 #endif
         }
@@ -738,7 +738,7 @@ void QSGPlainTexture::bind()
 
     }
 
-    Q_QML_SG_PROFILE1(QQmlProfilerService::SceneGraphTexturePrepare, (
+    Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTexturePrepare, (
             bindTime,
             convertTime - bindTime,
             swizzleTime - convertTime,
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 3bff2bb89070fe8746c25b5af623163c22bd5e0b..a7f91742191955ec5d54dac2a0643e265ef27da3 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -71,7 +71,7 @@
 #include <QQmlFile>
 #include <QMetaMethod>
 
-#include <private/qqmlprofilerservice_p.h>
+#include <private/qquickprofiler_p.h>
 
 #define IMAGEREQUEST_MAX_REQUEST_COUNT       8
 #define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
@@ -519,7 +519,7 @@ void QQuickPixmapReader::processJobs()
             runningJob->loading = true;
 
             QUrl url = runningJob->url;
-            Q_QML_PROFILE(pixmapStateChanged<QQmlProfilerService::PixmapLoadingStarted>(url));
+            Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
 
             QSize requestSize = runningJob->requestSize;
             locker.unlock();
@@ -897,10 +897,10 @@ bool QQuickPixmapReply::event(QEvent *event)
             if (data->pixmapStatus == QQuickPixmap::Ready) {
                 data->textureFactory = de->textureFactory;
                 data->implicitSize = de->implicitSize;
-                Q_QML_PROFILE(pixmapLoadingFinished(data->url,
+                Q_QUICK_PROFILE(pixmapLoadingFinished(data->url,
                         data->requestSize.width() > 0 ? data->requestSize : data->implicitSize));
             } else {
-                Q_QML_PROFILE(pixmapStateChanged<QQmlProfilerService::PixmapLoadingError>(data->url));
+                Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(data->url));
                 data->errorString = de->errorString;
                 data->removeFromCache(); // We don't continue to cache error'd pixmaps
             }
@@ -926,7 +926,7 @@ int QQuickPixmapData::cost() const
 void QQuickPixmapData::addref()
 {
     ++refCount;
-    Q_QML_PROFILE(pixmapCountChanged<QQmlProfilerService::PixmapReferenceCountChanged>(url, refCount));
+    Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
     if (prevUnreferencedPtr)
         pixmapStore()->referencePixmap(this);
 }
@@ -935,7 +935,7 @@ void QQuickPixmapData::release()
 {
     Q_ASSERT(refCount > 0);
     --refCount;
-    Q_QML_PROFILE(pixmapCountChanged<QQmlProfilerService::PixmapReferenceCountChanged>(url, refCount));
+    Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
     if (refCount == 0) {
         if (reply) {
             QQuickPixmapReply *cancelReply = reply;
@@ -966,7 +966,7 @@ void QQuickPixmapData::addToCache()
         QQuickPixmapKey key = { &url, &requestSize };
         pixmapStore()->m_cache.insert(key, this);
         inCache = true;
-        Q_QML_PROFILE(pixmapCountChanged<QQmlProfilerService::PixmapCacheCountChanged>(
+        Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
                 url, pixmapStore()->m_cache.count()));
     }
 }
@@ -975,7 +975,7 @@ void QQuickPixmapData::removeFromCache()
 {
     if (inCache) {
         QQuickPixmapKey key = { &url, &requestSize };
-        Q_QML_PROFILE(pixmapCountChanged<QQmlProfilerService::PixmapCacheCountChanged>(
+        Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
                 url, pixmapStore()->m_cache.count()));
         pixmapStore()->m_cache.remove(key);
         inCache = false;
@@ -1239,17 +1239,17 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
 
         if (!(options & QQuickPixmap::Asynchronous)) {
             bool ok = false;
-            Q_QML_PROFILE(pixmapStateChanged<QQmlProfilerService::PixmapLoadingStarted>(url));
+            Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
             d = createPixmapDataSync(this, engine, url, requestSize, &ok);
             if (ok) {
-                Q_QML_PROFILE(pixmapLoadingFinished(url,
+                Q_QUICK_PROFILE(pixmapLoadingFinished(url,
                         d->requestSize.width() > 0 ? d->requestSize : d->implicitSize));
                 if (options & QQuickPixmap::Cache)
                     d->addToCache();
                 return;
             }
             if (d) { // loadable, but encountered error while loading
-                Q_QML_PROFILE(pixmapStateChanged<QQmlProfilerService::PixmapLoadingError>(url));
+                Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
                 return;
             }
         }
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a706fb1e77b27c864cb3877cc201e5a269907d0a
--- /dev/null
+++ b/src/quick/util/qquickprofiler.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickprofiler_p.h"
+#include <private/qqmldebugservice_p.h>
+#include <private/qqmlprofilerservice_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// instance will be set, unset in constructor. Allows static methods to be inlined.
+QQuickProfiler *QQuickProfiler::s_instance = 0;
+bool QQuickProfiler::enabled = false;
+
+// convert to QByteArrays that can be sent to the debug client
+// use of QDataStream can skew results
+//     (see tst_qqmldebugtrace::trace() benchmark)
+void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
+{
+    QByteArray data;
+    Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types.");
+    for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) {
+        if ((messageType & (1 << decodedMessageType)) == 0)
+            continue;
+
+        for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) {
+            if ((detailType & (1 << decodedDetailType)) == 0)
+                continue;
+
+            //### using QDataStream is relatively expensive
+            QQmlDebugStream ds(&data, QIODevice::WriteOnly);
+            ds << time << decodedMessageType << decodedDetailType;
+
+            switch (decodedMessageType) {
+            case QQuickProfiler::Event:
+                if (decodedDetailType == (int)QQuickProfiler::AnimationFrame)
+                    ds << framerate << count;
+                break;
+            case QQuickProfiler::PixmapCacheEvent:
+                ds << detailUrl.toString();
+                switch (decodedDetailType) {
+                    case QQuickProfiler::PixmapSizeKnown: ds << x << y; break;
+                    case QQuickProfiler::PixmapReferenceCountChanged: ds << count; break;
+                    case QQuickProfiler::PixmapCacheCountChanged: ds << count; break;
+                    default: break;
+                }
+                break;
+            case QQuickProfiler::SceneGraphFrame:
+                switch (decodedDetailType) {
+                    // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
+                    case QQuickProfiler::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
+                    // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
+                    case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break;
+                    // ContextFrame: compiling material time
+                    case QQuickProfiler::SceneGraphContextFrame: ds << subtime_1; break;
+                    // RenderLoop: syncTime, renderTime, swapTime
+                    case QQuickProfiler::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
+                    // TexturePrepare: bind, convert, swizzle, upload, mipmap
+                    case QQuickProfiler::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break;
+                    // TextureDeletion: deletionTime
+                    case QQuickProfiler::SceneGraphTextureDeletion: ds << subtime_1; break;
+                    // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
+                    case QQuickProfiler::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
+                    // WindowsRenderLoop: GL time, make current time, SceneGraph time
+                    case QQuickProfiler::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break;
+                    // WindowsAnimations: update time
+                    case QQuickProfiler::SceneGraphWindowsAnimations: ds << subtime_1; break;
+                    // WindowsRenderWindow: polish time; always comes packed after a RenderLoop
+                    case QQuickProfiler::SceneGraphWindowsPolishFrame: ds << subtime_4; break;
+                    default:break;
+                }
+                break;
+            default:
+                Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+                break;
+            }
+            messages << data;
+            data.clear();
+        }
+    }
+}
+
+qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages)
+{
+    QMutexLocker lock(&m_dataMutex);
+    while (next < m_data.size() && m_data[next].time <= until) {
+        m_data[next++].toByteArrays(messages);
+    }
+    return next < m_data.size() ? m_data[next].time : -1;
+}
+
+void QQuickProfiler::initialize()
+{
+    Q_ASSERT(s_instance == 0);
+    QQmlProfilerService *service = QQmlProfilerService::instance();
+    s_instance = new QQuickProfiler(service);
+    QQmlProfilerService::instance()->addGlobalProfiler(s_instance);
+}
+
+void animationTimerCallback(qint64 delta)
+{
+    Q_QUICK_PROFILE(animationFrame(delta));
+}
+
+QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) :
+    QQmlAbstractProfilerAdapter(service), next(0)
+{
+    // This is safe because at this point the m_instance isn't initialized, yet.
+    m_timer.start();
+
+    // We can always do DirectConnection here as all methods are protected by mutexes
+    connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfilingImpl()),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfilingImpl()),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), this, SLOT(setTimer(QElapsedTimer)),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfilingImpl()),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfilingImpl()),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(dataRequested()), this, SLOT(reportDataImpl()),
+            Qt::DirectConnection);
+
+    QUnifiedTimer::instance()->registerProfilerCallback(&animationTimerCallback);
+}
+
+QQuickProfiler::~QQuickProfiler()
+{
+    QMutexLocker lock(&m_dataMutex);
+    enabled = false;
+    s_instance = 0;
+}
+
+void QQuickProfiler::startProfilingImpl()
+{
+    QMutexLocker lock(&m_dataMutex);
+    next = 0;
+    m_data.clear();
+    enabled = true;
+}
+
+void QQuickProfiler::stopProfilingImpl()
+{
+    {
+        QMutexLocker lock(&m_dataMutex);
+        enabled = false;
+        next = 0;
+    }
+    service->dataReady(this);
+}
+
+void QQuickProfiler::reportDataImpl()
+{
+    {
+        QMutexLocker lock(&m_dataMutex);
+        next = 0;
+    }
+    service->dataReady(this);
+}
+
+void QQuickProfiler::setTimer(const QElapsedTimer &t)
+{
+    QMutexLocker lock(&m_dataMutex);
+    m_timer = t;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5ad0e9285cde1372ad8e25f308a96b6e177e3cf
--- /dev/null
+++ b/src/quick/util/qquickprofiler_p.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPROFILER_P_H
+#define QQUICKPROFILER_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qqmlabstractprofileradapter_p.h"
+#include <private/qabstractanimation_p.h>
+#include <QUrl>
+#include <QSize>
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+
+#define Q_QUICK_PROFILE_IF_ENABLED(Code)\
+    if (QQuickProfiler::enabled) {\
+        Code;\
+    } else\
+        (void)0
+
+#define Q_QUICK_PROFILE(Method)\
+    Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::Method)
+
+#define Q_QUICK_SG_PROFILE2(Type1, Type2, Params)\
+    Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::sceneGraphFrame<Type1, Type2> Params))
+
+#define Q_QUICK_SG_PROFILE1(Type, Params) Q_QUICK_SG_PROFILE2(Type, Type, Params)
+
+
+// This struct is somewhat dangerous to use:
+// You can save values either with 32 or 64 bit precision. toByteArrays will
+// guess the precision from messageType. If you state the wrong messageType
+// you will get undefined results.
+// The messageType is itself a bit field. You can pack multiple messages into
+// one object, e.g. RangeStart and RangeLocation. Each one will be read
+// independently by toByteArrays. Thus you can only pack messages if their data
+// doesn't overlap. Again, it's up to you to figure that out.
+struct Q_AUTOTEST_EXPORT QQuickProfilerData
+{
+    QQuickProfilerData() {}
+
+    QQuickProfilerData(qint64 time, int messageType, int detailType, const QUrl &url, int x = 0,
+                       int y = 0, int framerate = 0, int count = 0) :
+        time(time), messageType(messageType), detailType(detailType), detailUrl(url), x(x), y(y),
+        framerate(framerate), count(count) {}
+
+    QQuickProfilerData(qint64 time, int messageType, int detailType, int framerate = 0,
+                       int count = 0) :
+        time(time), messageType(messageType), detailType(detailType), framerate(framerate),
+        count(count) {}
+
+    // Special ctor for scenegraph frames. Note that it's missing the QString/QUrl params.
+    // This is slightly ugly, but makes it easier to disambiguate between int and qint64 params.
+    QQuickProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2,
+                       qint64 d3, qint64 d4, qint64 d5) :
+        time(time), messageType(messageType), detailType(detailType), subtime_1(d1), subtime_2(d2),
+        subtime_3(d3), subtime_4(d4), subtime_5(d5) {}
+
+
+    qint64 time;
+    int messageType;        //bit field of Message
+    int detailType;
+
+    QUrl detailUrl;
+
+    union {
+        qint64 subtime_1;
+        int x;              //used for pixmaps
+    };
+
+    union {
+        qint64 subtime_2;
+        int y;              //used for pixmaps
+    };
+
+    union {
+        qint64 subtime_3;
+        int framerate;      //used by animation events
+    };
+
+    union {
+        qint64 subtime_4;
+        int count;          //used by animation events and for pixmaps
+    };
+
+    qint64 subtime_5;
+
+    void toByteArrays(QList<QByteArray> &messages) const;
+};
+
+Q_DECLARE_TYPEINFO(QQuickProfilerData, Q_MOVABLE_TYPE);
+
+class QQuickProfiler : public QQmlAbstractProfilerAdapter {
+    Q_OBJECT
+public:
+
+    template<EventType DetailType>
+    static void addEvent()
+    {
+        s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
+                1 << DetailType));
+    }
+
+    static void animationFrame(qint64 delta)
+    {
+        int animCount = QUnifiedTimer::instance()->runningAnimationCount();
+
+        if (animCount > 0 && delta > 0) {
+            s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
+                    1 << AnimationFrame, 1000 / (int)delta /* trim fps to integer */, animCount));
+        }
+    }
+
+    template<SceneGraphFrameType FrameType1, SceneGraphFrameType FrameType2>
+    static void sceneGraphFrame(qint64 value1, qint64 value2 = -1, qint64 value3 = -1,
+                                qint64 value4 = -1, qint64 value5 = -1)
+    {
+        s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << SceneGraphFrame,
+                1 << FrameType1 | 1 << FrameType2, value1, value2, value3, value4, value5));
+    }
+
+    template<PixmapEventType PixmapState>
+    static void pixmapStateChanged(const QUrl &url)
+    {
+        s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+                1 << PixmapCacheEvent, 1 << PixmapState, url));
+    }
+
+    static void pixmapLoadingFinished(const QUrl &url, const QSize &size)
+    {
+        s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+                1 << PixmapCacheEvent,
+                (1 << PixmapLoadingFinished) | ((size.width() > 0 && size.height() > 0) ? (1 << PixmapSizeKnown) : 0),
+                url, size.width(), size.height()));
+    }
+
+    template<PixmapEventType CountType>
+    static void pixmapCountChanged(const QUrl &url, int count)
+    {
+        s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
+                1 << PixmapCacheEvent, 1 << CountType, url, 0, 0, 0, count));
+    }
+
+    qint64 timestamp() { return m_timer.nsecsElapsed(); }
+
+    qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+
+    static bool enabled;
+
+    static void initialize();
+
+    virtual ~QQuickProfiler();
+
+protected:
+    int next;
+    static QQuickProfiler *s_instance;
+    QMutex m_dataMutex;
+    QElapsedTimer m_timer;
+    QVarLengthArray<QQuickProfilerData> m_data;
+
+    QQuickProfiler(QQmlProfilerService *service);
+
+    void processMessage(const QQuickProfilerData &message)
+    {
+        QMutexLocker lock(&m_dataMutex);
+        m_data.append(message);
+    }
+
+protected slots:
+    void startProfilingImpl();
+    void stopProfilingImpl();
+    void reportDataImpl();
+    void setTimer(const QElapsedTimer &t);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index fae1103d47a4c81fb99052d3b3f73a6a902c5653..ce409bd10dff64b4280f5a63fa0916450dc4f1d0 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -25,7 +25,8 @@ SOURCES += \
     $$PWD/qquickglobal.cpp \
     $$PWD/qquickanimator.cpp \
     $$PWD/qquickanimatorjob.cpp \
-    $$PWD/qquickanimatorcontroller.cpp
+    $$PWD/qquickanimatorcontroller.cpp \
+    $$PWD/qquickprofiler.cpp
 
 HEADERS += \
     $$PWD/qquickapplication_p.h\
@@ -58,4 +59,5 @@ HEADERS += \
     $$PWD/qquickanimator_p.h \
     $$PWD/qquickanimator_p_p.h \
     $$PWD/qquickanimatorjob_p.h \
-    $$PWD/qquickanimatorcontroller_p.h
+    $$PWD/qquickanimatorcontroller_p.h \
+    $$PWD/qquickprofiler_p.h