Bug 1470528 - Implement CONTENT_FRAME_TIME for the non-webrender codepath. r=sotaro

This commit adds the CONTENT_FRAME_TIME metric which tracks the time from the beginning
of a paint in the content process until it is presented in the compositor.

There is existing logging for frame latency which tracks from the beginning of a refresh
tick until the frame is presented. This is undesirable for this probe as javascript and
layout can run in this time period. So this probe uses the existing infrastructure for
logging frame latency, but uses a start time from BeginTransaction in layer manager.

MozReview-Commit-ID: 5z9LS3tsZTY

--HG--
extra : rebase_source : cecb7149f50b2abe7a827dc20f1e8b8ade199258
extra : histedit_source : 581f8f38fc8335575d7275b903a8e1d6a9e5a369
This commit is contained in:
Ryan Hunt 2018-06-26 13:40:10 -05:00
Родитель 5ca70b4c61
Коммит d34e6c84a0
10 изменённых файлов: 62 добавлений и 22 удалений

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

@ -436,9 +436,15 @@ ClientLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
if (mRepeatTransaction) {
mRepeatTransaction = false;
mIsRepeatTransaction = true;
// BeginTransaction will reset the transaction start time, but we
// would like to keep the original time for telemetry purposes.
TimeStamp transactionStart = mTransactionStart;
if (BeginTransaction()) {
mTransactionStart = transactionStart;
ClientLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
}
mIsRepeatTransaction = false;
} else {
MakeSnapshotIfRequired();
@ -755,12 +761,7 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
mPhase = PHASE_FORWARD;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
TimeStamp transactionStart;
if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) {
transactionStart = mTransactionIdAllocator->GetTransactionStart();
} else {
transactionStart = mTransactionStart;
}
TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime);
@ -770,7 +771,8 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
bool sent = false;
bool ok = mForwarder->EndTransaction(
mRegionToClear, mLatestTransactionId, aScheduleComposite,
mPaintSequenceNumber, mIsRepeatTransaction, transactionStart,
mPaintSequenceNumber, mIsRepeatTransaction,
refreshStart, mTransactionStart,
&sent);
if (ok) {
if (sent) {

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

@ -1328,6 +1328,7 @@ CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
// Otherwise, it should be continually increasing.
MOZ_ASSERT(aInfo.id() == TransactionId{1} || aInfo.id() > mPendingTransaction);
mPendingTransaction = aInfo.id();
mRefreshStartTime = aInfo.refreshStart();
mTxnStartTime = aInfo.transactionStart();
mFwdTime = aInfo.fwdTime();
@ -1636,14 +1637,14 @@ CompositorBridgeParent::AllocPLayerTransactionParent(const nsTArray<LayersBacken
if (!mLayerManager) {
NS_WARNING("Failed to initialise Compositor");
LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, mRootLayerTreeID);
LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, mRootLayerTreeID, mVsyncRate);
p->AddIPDLReference();
return p;
}
mCompositionManager = new AsyncCompositionManager(this, mLayerManager);
LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(), mRootLayerTreeID);
LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(), mRootLayerTreeID, mVsyncRate);
p->AddIPDLReference();
return p;
}
@ -2131,15 +2132,16 @@ CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mPendingTransaction.IsValid()) {
if (mTxnStartTime) {
uint32_t latencyMs = round((aCompositeEnd - mTxnStartTime).ToMilliseconds());
if (mRefreshStartTime) {
int32_t latencyMs = lround((aCompositeEnd - mRefreshStartTime).ToMilliseconds());
printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
}
if (mFwdTime) {
uint32_t latencyMs = round((aCompositeEnd - mFwdTime).ToMilliseconds());
int32_t latencyMs = lround((aCompositeEnd - mFwdTime).ToMilliseconds());
printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
}
}
mRefreshStartTime = TimeStamp();
mTxnStartTime = TimeStamp();
mFwdTime = TimeStamp();
#endif

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

@ -601,6 +601,7 @@ protected:
TimeDuration mVsyncRate;
TransactionId mPendingTransaction;
TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime;
TimeStamp mFwdTime;

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

@ -94,14 +94,15 @@ CrossProcessCompositorBridgeParent::AllocPLayerTransactionParent(
state->mCrossProcessParent = this;
HostLayerManager* lm = state->mLayerManager;
CompositorAnimationStorage* animStorage = state->mParent ? state->mParent->GetAnimationStorage() : nullptr;
LayerTransactionParent* p = new LayerTransactionParent(lm, this, animStorage, aId);
TimeDuration vsyncRate = state->mParent ? state->mParent->GetVsyncInterval() : TimeDuration();
LayerTransactionParent* p = new LayerTransactionParent(lm, this, animStorage, aId, vsyncRate);
p->AddIPDLReference();
sIndirectLayerTrees[aId].mLayerTree = p;
return p;
}
NS_WARNING("Created child without a matching parent?");
LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, aId);
LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, aId, TimeDuration());
p->AddIPDLReference();
return p;
}
@ -372,7 +373,7 @@ CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
}
aLayerTree->SetPendingTransactionId(aInfo.id(), aInfo.transactionStart(), aInfo.fwdTime());
aLayerTree->SetPendingTransactionId(aInfo.id(), aInfo.refreshStart(), aInfo.transactionStart(), aInfo.fwdTime());
}
void

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

@ -26,6 +26,7 @@
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
#include "mozilla/layers/PaintedLayerComposite.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "mozilla/Telemetry.h"
#include "mozilla/Unused.h"
#include "nsCoord.h" // for NSAppUnitsToFloatPixels
#include "nsISupportsImpl.h" // for Layer::Release, etc
@ -48,13 +49,15 @@ namespace layers {
LayerTransactionParent::LayerTransactionParent(HostLayerManager* aManager,
CompositorBridgeParentBase* aBridge,
CompositorAnimationStorage* aAnimStorage,
LayersId aId)
LayersId aId,
TimeDuration aVsyncRate)
: mLayerManager(aManager)
, mCompositorBridge(aBridge)
, mAnimStorage(aAnimStorage)
, mId(aId)
, mChildEpoch(0)
, mParentEpoch(0)
, mVsyncRate(aVsyncRate)
, mPendingTransaction{0}
, mDestroyed(false)
, mIPCOpen(false)
@ -959,20 +962,29 @@ bool LayerTransactionParent::IsSameProcess() const
TransactionId
LayerTransactionParent::FlushTransactionId(TimeStamp& aCompositeEnd)
{
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds();
double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm);
}
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mPendingTransaction.IsValid()) {
if (mTxnStartTime) {
uint32_t latencyMs = round((aCompositeEnd - mTxnStartTime).ToMilliseconds());
if (mRefreshStartTime) {
int32_t latencyMs = lround((aCompositeEnd - mRefreshStartTime).ToMilliseconds());
printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
}
if (mFwdTime) {
uint32_t latencyMs = round((aCompositeEnd - mFwdTime).ToMilliseconds());
int32_t latencyMs = lround((aCompositeEnd - mFwdTime).ToMilliseconds());
printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
}
}
#endif
mRefreshStartTime = TimeStamp();
mTxnStartTime = TimeStamp();
mFwdTime = TimeStamp();
#endif
TransactionId id = mPendingTransaction;
mPendingTransaction = TransactionId{0};
return id;

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

@ -48,7 +48,8 @@ public:
LayerTransactionParent(HostLayerManager* aManager,
CompositorBridgeParentBase* aBridge,
CompositorAnimationStorage* aAnimStorage,
LayersId aId);
LayersId aId,
TimeDuration aVsyncRate);
protected:
~LayerTransactionParent();
@ -79,9 +80,13 @@ public:
bool IsSameProcess() const override;
const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
void SetPendingTransactionId(TransactionId aId, const TimeStamp& aTxnStartTime, const TimeStamp& aFwdTime)
void SetPendingTransactionId(TransactionId aId,
const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime,
const TimeStamp& aFwdTime)
{
mPendingTransaction = aId;
mRefreshStartTime = aRefreshStartTime;
mTxnStartTime = aTxnStartTime;
mFwdTime = aFwdTime;
}
@ -196,7 +201,10 @@ private:
uint64_t mChildEpoch;
uint64_t mParentEpoch;
TimeDuration mVsyncRate;
TransactionId mPendingTransaction;
TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime;
TimeStamp mFwdTime;

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

@ -572,6 +572,7 @@ struct TransactionInfo
bool scheduleComposite;
uint32_t paintSequenceNumber;
bool isRepeatTransaction;
TimeStamp refreshStart;
TimeStamp transactionStart;
TimeStamp fwdTime;
};

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

@ -604,6 +604,7 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
bool aScheduleComposite,
uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction,
const mozilla::TimeStamp& aRefreshStart,
const mozilla::TimeStamp& aTransactionStart,
bool* aSent)
{
@ -745,6 +746,7 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear,
info.scheduleComposite() = aScheduleComposite;
info.paintSequenceNumber() = aPaintSequenceNumber;
info.isRepeatTransaction() = aIsRepeatTransaction;
info.refreshStart() = aRefreshStart;
info.transactionStart() = aTransactionStart;
#if defined(ENABLE_FRAME_LATENCY_LOG)
info.fwdTime() = TimeStamp::Now();

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

@ -258,6 +258,7 @@ public:
bool aScheduleComposite,
uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction,
const mozilla::TimeStamp& aRefreshStart,
const mozilla::TimeStamp& aTransactionStart,
bool* aSent);

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

@ -12801,6 +12801,16 @@
"n_buckets": 50,
"description": "Time spent in the paint pipeline for content in milliseconds."
},
"CONTENT_FRAME_TIME": {
"record_in_processes": ["main", "gpu"],
"alert_emails": ["rhunt@mozilla.com","gfx-telemetry-alerts@mozilla.com"],
"bug_numbers": [1470528],
"expires_in_version": "66",
"kind": "exponential",
"high": 5000,
"n_buckets": 50,
"description": "The time, in percentage of a vsync interval, spent from beginning a paint in the content process until that frame is presented in the compositor."
},
"CONTENT_LARGE_PAINT_PHASE_WEIGHT": {
"record_in_processes": ["main", "content"],
"alert_emails": ["mwoodrow@mozilla.com","gfx-telemetry-alerts@mozilla.com"],