Collect diagnostics on paint times for the compositor overlay. (bug 1352151 part 1, r=mattwoodrow)

--HG--
extra : rebase_source : f30dc11079add3f1019777b1c85cc5c5a5f0596b
This commit is contained in:
David Anderson 2017-04-10 19:44:45 -07:00
Родитель 1d72f5911e
Коммит a8433cef6b
18 изменённых файлов: 307 добавлений и 4 удалений

Просмотреть файл

@ -316,6 +316,11 @@ ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization);
GeckoProfilerTracingRAII tracer("Paint", "Rasterize");
Maybe<TimeStamp> startTime;
if (gfxPrefs::LayersDrawFPS()) {
startTime = Some(TimeStamp::Now());
}
#ifdef WIN32
if (aCallbackData) {
// Content processes don't get OnPaint called. So update here whenever we
@ -384,6 +389,11 @@ ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
FrameLayerBuilder::InvalidateAllLayers(this);
}
if (startTime) {
PaintTiming& pt = mForwarder->GetPaintTiming();
pt.rasterMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds();
}
return !mTransactionIncomplete;
}

Просмотреть файл

@ -240,6 +240,16 @@ public:
virtual already_AddRefed<PersistentBufferProvider>
CreatePersistentBufferProvider(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat) override;
static PaintTiming* MaybeGetPaintTiming(LayerManager* aManager) {
if (!aManager) {
return nullptr;
}
if (ClientLayerManager* lm = aManager->AsClientLayerManager()) {
return &lm->AsShadowForwarder()->GetPaintTiming();
}
return nullptr;
}
protected:
enum TransactionPhase {
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD

Просмотреть файл

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Diagnostics.h"
#include "mozilla/layers/LayersMessages.h"
#include "nsPrintfCString.h"
namespace mozilla {
namespace layers {
float
TimedMetric::Average() const
{
// We take at most 2 seconds of history.
TimeStamp latest = TimeStamp::Now();
float total = 0.0f;
size_t count = 0;
for (auto iter = mHistory.rbegin(); iter != mHistory.rend(); iter++) {
if ((latest - iter->second).ToSeconds() > 2.0f) {
break;
}
total += iter->first;
count++;
}
if (!count) {
return 0.0f;
}
return total / float(count);
}
Diagnostics::Diagnostics()
: mCompositeFps("Compositor"),
mTransactionFps("LayerTransactions")
{
}
void
Diagnostics::RecordPaintTimes(const PaintTiming& aPaintTimes)
{
mDlbMs.Add(aPaintTimes.dlMs());
mFlbMs.Add(aPaintTimes.flbMs());
mRasterMs.Add(aPaintTimes.rasterMs());
mSerializeMs.Add(aPaintTimes.serializeMs());
mSendMs.Add(aPaintTimes.sendMs());
}
std::string
Diagnostics::GetFrameOverlayString()
{
TimeStamp now = TimeStamp::Now();
unsigned fps = unsigned(mCompositeFps.AddFrameAndGetFps(now));
unsigned txnFps = unsigned(mTransactionFps.GetFPS(now));
// DL = nsDisplayListBuilder
// FLB = FrameLayerBuilder
// R = ClientLayerManager::EndTransaction
// CP = ShadowLayerForwarder::EndTransaction (txn build)
// TX = LayerTransactionChild::SendUpdate (IPDL serialize+send)
// UP = LayerTransactionParent::RecvUpdate (IPDL deserialize, update, APZ update)
// CC_BUILD = Container prepare/composite frame building
// CC_EXEC = Container render/composite drawing
nsPrintfCString line1("FPS: %d (TXN: %d)", fps, txnFps);
nsPrintfCString line2("CC_BUILD: %0.1f CC_EXEC: %0.1f",
mPrepareMs.Average(),
mCompositeMs.Average());
nsPrintfCString line3("DL: %0.1f FLB: %0.1f R: %0.1f CP: %0.1f TX: %0.1f UP: %0.1f",
mDlbMs.Average(),
mFlbMs.Average(),
mRasterMs.Average(),
mSerializeMs.Average(),
mSendMs.Average(),
mUpdateMs.Average());
return std::string(line1.get()) + ", " + std::string(line2.get()) + "\n" + std::string(line3.get());
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_gfx_layers_composite_Diagnostics_h
#define mozilla_gfx_layers_composite_Diagnostics_h
#include "FPSCounter.h"
#include "gfxPrefs.h"
#include "mozilla/TimeStamp.h"
#include <deque>
#include <string>
#include <utility>
namespace mozilla {
namespace layers {
class PaintTiming;
class TimedMetric
{
typedef std::pair<float, TimeStamp> Entry;
public:
void Add(float aValue) {
if (mHistory.size() > kMaxHistory) {
mHistory.pop_front();
}
mHistory.push_back(Entry(aValue, TimeStamp::Now()));
}
float Average() const;
private:
static const size_t kMaxHistory = 60;
std::deque<Entry> mHistory;
};
class Diagnostics
{
public:
Diagnostics();
void RecordPaintTimes(const PaintTiming& aPaintTimes);
void RecordUpdateTime(float aValue) {
mUpdateMs.Add(aValue);
}
void RecordPrepareTime(float aValue) {
mPrepareMs.Add(aValue);
}
void RecordCompositeTime(float aValue) {
mCompositeMs.Add(aValue);
}
void AddTxnFrame() {
mTransactionFps.AddFrame(TimeStamp::Now());
}
std::string GetFrameOverlayString();
class Record {
public:
Record() {
if (gfxPrefs::LayersDrawFPS()) {
mStart = TimeStamp::Now();
}
}
bool Recording() const {
return !mStart.IsNull();
}
float Duration() const {
return (TimeStamp::Now() - mStart).ToMilliseconds();
}
private:
TimeStamp mStart;
};
private:
FPSCounter mCompositeFps;
FPSCounter mTransactionFps;
TimedMetric mDlbMs;
TimedMetric mFlbMs;
TimedMetric mRasterMs;
TimedMetric mSerializeMs;
TimedMetric mSendMs;
TimedMetric mUpdateMs;
TimedMetric mPrepareMs;
TimedMetric mCompositeMs;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_gfx_layers_composite_Diagnostics_h

Просмотреть файл

@ -10,6 +10,7 @@
#include "ColorLayerComposite.h" // for ColorLayerComposite
#include "CompositableHost.h" // for CompositableHost
#include "ContainerLayerComposite.h" // for ContainerLayerComposite, etc
#include "Diagnostics.h"
#include "FPSCounter.h" // for FPSState, FPSCounter
#include "FrameMetrics.h" // for FrameMetrics
#include "GeckoProfiler.h" // for profiler_set_frame_number, etc
@ -124,6 +125,19 @@ HostLayerManager::HostLayerManager()
HostLayerManager::~HostLayerManager()
{}
void
HostLayerManager::RecordPaintTimes(const PaintTiming& aTiming)
{
mDiagnostics->RecordPaintTimes(aTiming);
}
void
HostLayerManager::RecordUpdateTime(float aValue)
{
mDiagnostics->RecordUpdateTime(aValue);
}
/**
* LayerManagerComposite
*/
@ -136,6 +150,7 @@ LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
, mGeometryChanged(true)
{
mTextRenderer = new TextRenderer(aCompositor);
mDiagnostics = MakeUnique<Diagnostics>();
MOZ_ASSERT(aCompositor);
#ifdef USE_SKIA
@ -925,8 +940,21 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion, const nsIntRegi
}
// Render our layers.
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
RootLayer()->RenderLayer(clipRect.ToUnknownRect(), Nothing());
{
Diagnostics::Record record;
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
if (record.Recording()) {
mDiagnostics->RecordPrepareTime(record.Duration());
}
}
// Execute draw commands.
{
Diagnostics::Record record;
RootLayer()->RenderLayer(clipRect.ToUnknownRect(), Nothing());
if (record.Recording()) {
mDiagnostics->RecordCompositeTime(record.Duration());
}
}
RootLayer()->Cleanup();
if (!mRegionToClear.IsEmpty()) {

Просмотреть файл

@ -52,6 +52,7 @@ class CanvasLayerComposite;
class ColorLayerComposite;
class Compositor;
class ContainerLayerComposite;
class Diagnostics;
struct EffectChain;
class ImageLayer;
class ImageLayerComposite;
@ -169,6 +170,9 @@ public:
return false;
}
void RecordPaintTimes(const PaintTiming& aTiming);
void RecordUpdateTime(float aValue);
TimeStamp GetCompositionTime() const {
return mCompositionTime;
}
@ -196,6 +200,7 @@ protected:
// true if the last frame was deemed 'too complicated' to be rendered.
float mWarningLevel;
mozilla::TimeStamp mWarnTime;
UniquePtr<Diagnostics> mDiagnostics;
bool mWindowOverlayChanged;
TimeDuration mLastPaintTime;

Просмотреть файл

@ -147,6 +147,10 @@ public:
uint32_t aApzcId) override;
bool StopSharingMetrics(FrameMetrics::ViewID aScrollId,
uint32_t aApzcId) override;
virtual bool IsRemote() const {
return false;
}
};
class CompositorBridgeParent final : public CompositorBridgeParentBase

Просмотреть файл

@ -161,6 +161,10 @@ public:
void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) override;
bool IsRemote() const override {
return true;
}
protected:
void OnChannelConnected(int32_t pid) override {
mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();

Просмотреть файл

@ -149,9 +149,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
PROFILER_LABEL("LayerTransactionParent", "RecvUpdate",
js::ProfileEntry::Category::GRAPHICS);
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp updateStart = TimeStamp::Now();
#endif
MOZ_LAYERS_LOG(("[ParentSide] received txn with %" PRIuSIZE " edits", aInfo.cset().Length()));
@ -506,6 +504,8 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
OtherPid(),
latency.ToMilliseconds());
}
mLayerManager->RecordUpdateTime((TimeStamp::Now() - updateStart).ToMilliseconds());
}
return IPC_OK();
@ -1026,5 +1026,17 @@ LayerTransactionParent::RecvReleaseCompositable(const CompositableHandle& aHandl
return IPC_OK();
}
mozilla::ipc::IPCResult
LayerTransactionParent::RecvRecordPaintTimes(const PaintTiming& aTiming)
{
// Currently we only add paint timings for remote layers. In the future
// we could be smarter and use paint timings from the UI process, either
// as a separate overlay or if no remote layers are attached.
if (mLayerManager && mCompositorBridge->IsRemote()) {
mLayerManager->RecordPaintTimes(aTiming);
}
return IPC_OK();
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -140,6 +140,7 @@ protected:
virtual mozilla::ipc::IPCResult RecvRequestProperty(const nsString& aProperty, float* aValue) override;
virtual mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) override;
virtual mozilla::ipc::IPCResult RecvRecordPaintTimes(const PaintTiming& aTiming) override;
bool SetLayerAttributes(const OpSetLayerAttributes& aOp);

Просмотреть файл

@ -534,6 +534,14 @@ union AsyncParentMessageData {
OpNotifyNotUsed;
};
struct PaintTiming {
float serializeMs;
float sendMs;
float dlMs;
float flbMs;
float rasterMs;
};
struct TransactionInfo
{
Edit[] cset;

Просмотреть файл

@ -122,6 +122,8 @@ parent:
// input event.
async SetConfirmedTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
async RecordPaintTimes(PaintTiming timing);
async Shutdown();
child:
async __delete__();

Просмотреть файл

@ -15,6 +15,7 @@
#include "RenderTrace.h" // for RenderTraceScope
#include "gfx2DGlue.h" // for Moz2D transition helpers
#include "gfxPlatform.h" // for gfxImageFormat, gfxPlatform
#include "gfxPrefs.h"
//#include "gfxSharedImageSurface.h" // for gfxSharedImageSurface
#include "ipc/IPCMessageUtils.h" // for gfxContentType, null_t
#include "IPDLActor.h"
@ -586,6 +587,11 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
return false;
}
Maybe<TimeStamp> startTime;
if (gfxPrefs::LayersDrawFPS()) {
startTime = Some(TimeStamp::Now());
}
GetCompositorBridgeChild()->WillEndTransaction();
MOZ_ASSERT(aId);
@ -724,6 +730,11 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
PlatformSyncBeforeUpdate();
}
if (startTime) {
mPaintTiming.serializeMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds();
startTime = Some(TimeStamp::Now());
}
for (ReadLockVector& locks : mTxn->mReadLocks) {
if (locks.Length()) {
if (!mShadowManager->SendInitReadLocks(locks)) {
@ -740,6 +751,11 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
return false;
}
if (startTime) {
mPaintTiming.sendMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds();
mShadowManager->SendRecordPaintTimes(mPaintTiming);
}
*aSent = true;
mIsFirstPaint = false;
mPaintSyncId = 0;

Просмотреть файл

@ -392,6 +392,10 @@ public:
return NS_IsMainThread();
}
PaintTiming& GetPaintTiming() {
return mPaintTiming;
}
// Returns true if aSurface wraps a Shmem.
static bool IsShmem(SurfaceDescriptor* aSurface);
@ -442,6 +446,7 @@ private:
UniquePtr<ActiveResourceTracker> mActiveResourceTracker;
uint64_t mNextLayerHandle;
nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
PaintTiming mPaintTiming;
};
class CompositableClient;

Просмотреть файл

@ -316,6 +316,7 @@ UNIFIED_SOURCES += [
'composite/CompositableHost.cpp',
'composite/ContainerLayerComposite.cpp',
'composite/ContentHost.cpp',
'composite/Diagnostics.cpp',
'composite/FPSCounter.cpp',
'composite/FrameUniformityData.cpp',
'composite/GPUVideoTextureHost.cpp',

Просмотреть файл

@ -3672,6 +3672,14 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
}
builder.LeavePresShell(aFrame, &list);
if (!record.GetStart().IsNull() && gfxPrefs::LayersDrawFPS()) {
if (RefPtr<LayerManager> lm = builder.GetWidgetLayerManager()) {
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(lm)) {
pt->dlMs() = (TimeStamp::Now() - record.GetStart()).ToMilliseconds();
}
}
}
}
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,

Просмотреть файл

@ -83,6 +83,7 @@
#include "nsCSSProps.h"
#include "nsPluginFrame.h"
#include "nsSVGMaskFrame.h"
#include "ClientLayerManager.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/WebRenderDisplayItemLayer.h"
@ -2115,9 +2116,16 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
{
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
root = layerBuilder->
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
containerParameters, nullptr);
if (!record.GetStart().IsNull() && gfxPrefs::LayersDrawFPS()) {
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(layerManager)) {
pt->flbMs() = (TimeStamp::Now() - record.GetStart()).ToMilliseconds();
}
}
}
if (!root) {

Просмотреть файл

@ -4922,6 +4922,10 @@ class PaintTelemetry
public:
explicit AutoRecord(Metric aMetric);
~AutoRecord();
TimeStamp GetStart() const {
return mStart;
}
private:
Metric mMetric;
mozilla::TimeStamp mStart;