Skip to content

Commit 649c895

Browse files
author
Mike Kaufman
committed
[MERGE #5161 @mike-kaufman] Only capture recycler stats if telemetry provider is enabled.
Merge pull request #5161 from mike-kaufman:build/mkaufman/only-compute-telemetry-when-something-listening This will avoid most work in scenarios where telemetry data is not being captured, which is for the majority of users when we actually ship.
2 parents c7c6c6e + 84e7547 commit 649c895

File tree

4 files changed

+88
-70
lines changed

4 files changed

+88
-70
lines changed

lib/Common/Memory/RecyclerTelemetryInfo.cpp

Lines changed: 73 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ namespace Memory
2626
hostInterface(hostInterface),
2727
lastPassStats(nullptr),
2828
recyclerStartTime(Js::Tick::Now()),
29-
abortTelemetryCapture(false)
29+
abortTelemetryCapture(false),
30+
inPassActiveState(false),
31+
recycler(recycler)
3032
{
31-
this->recycler = recycler;
3233
mainThreadID = ::GetCurrentThreadId();
3334
}
3435

@@ -52,11 +53,15 @@ namespace Memory
5253
return this->recycler->IsConcurrentEnabled();
5354
}
5455

55-
bool RecyclerTelemetryInfo::ShouldCaptureRecyclerTelemetry() const
56+
bool RecyclerTelemetryInfo::ShouldStartTelemetryCapture() const
5657
{
57-
return this->hostInterface != nullptr && this->abortTelemetryCapture == false;
58+
return
59+
this->hostInterface != nullptr &&
60+
this->abortTelemetryCapture == false &&
61+
this->hostInterface->IsTelemetryProviderEnabled();
5862
}
5963

64+
6065
void RecyclerTelemetryInfo::FillInSizeData(IdleDecommitPageAllocator* allocator, AllocatorSizes* sizes) const
6166
{
6267
sizes->committedBytes = allocator->GetCommittedBytes();
@@ -67,86 +72,86 @@ namespace Memory
6772

6873
void RecyclerTelemetryInfo::StartPass()
6974
{
70-
Js::Tick start = Js::Tick::Now();
71-
if (!this->ShouldCaptureRecyclerTelemetry())
75+
this->inPassActiveState = false;
76+
if (this->ShouldStartTelemetryCapture())
7277
{
73-
return;
74-
}
75-
76-
AssertOnValidThread(this, RecyclerTelemetryInfo::StartPass);
78+
Js::Tick start = Js::Tick::Now();
79+
AssertOnValidThread(this, RecyclerTelemetryInfo::StartPass);
7780
#if DBG
78-
// validate state of existing GC pass stats structs
79-
uint16 count = 0;
80-
if (this->lastPassStats != nullptr)
81-
{
82-
RecyclerTelemetryGCPassStats* head = this->lastPassStats->next;
83-
RecyclerTelemetryGCPassStats* curr = head;
84-
do
81+
// validate state of existing GC pass stats structs
82+
uint16 count = 0;
83+
if (this->lastPassStats != nullptr)
8584
{
86-
AssertMsg(curr->isGCPassActive == false, "unexpected value for isGCPassActive");
87-
count++;
88-
curr = curr->next;
89-
} while (curr != head);
90-
}
91-
AssertMsg(count == this->passCount, "RecyclerTelemetryInfo::StartPass() - mismatch between passCount and count.");
85+
RecyclerTelemetryGCPassStats* head = this->lastPassStats->next;
86+
RecyclerTelemetryGCPassStats* curr = head;
87+
do
88+
{
89+
AssertMsg(curr->isGCPassActive == false, "unexpected value for isGCPassActive");
90+
count++;
91+
curr = curr->next;
92+
} while (curr != head);
93+
}
94+
AssertMsg(count == this->passCount, "RecyclerTelemetryInfo::StartPass() - mismatch between passCount and count.");
9295
#endif
9396

94-
RecyclerTelemetryGCPassStats* p = HeapNewNoThrow(RecyclerTelemetryGCPassStats);
95-
if (p == nullptr)
96-
{
97-
// failed to allocate memory - disable any further telemetry capture for this recycler
98-
// and free any existing GC stats we've accumulated
99-
this->abortTelemetryCapture = true;
100-
FreeGCPassStats();
101-
this->hostInterface->TransmitTelemetryError(*this, "Memory Allocation Failed");
102-
}
103-
else
104-
{
105-
passCount++;
106-
memset(p, 0, sizeof(RecyclerTelemetryGCPassStats));
107-
if (this->lastPassStats == nullptr)
97+
RecyclerTelemetryGCPassStats* p = HeapNewNoThrow(RecyclerTelemetryGCPassStats);
98+
if (p == nullptr)
10899
{
109-
p->next = p;
100+
// failed to allocate memory - disable any further telemetry capture for this recycler
101+
// and free any existing GC stats we've accumulated
102+
this->abortTelemetryCapture = true;
103+
FreeGCPassStats();
104+
this->hostInterface->TransmitTelemetryError(*this, "Memory Allocation Failed");
110105
}
111106
else
112107
{
113-
p->next = lastPassStats->next;
114-
this->lastPassStats->next = p;
115-
}
116-
this->lastPassStats = p;
117-
118-
this->lastPassStats->isGCPassActive = true;
119-
this->lastPassStats->passStartTimeTick = Js::Tick::Now();
120-
GetSystemTimePreciseAsFileTime(&this->lastPassStats->passStartTimeFileTime);
121-
if (this->hostInterface != nullptr)
122-
{
123-
LPFILETIME ft = this->hostInterface->GetLastScriptExecutionEndTime();
124-
this->lastPassStats->lastScriptExecutionEndTime = *ft;
125-
}
126-
127-
this->lastPassStats->processCommittedBytes_start = RecyclerTelemetryInfo::GetProcessCommittedBytes();
128-
this->lastPassStats->processAllocaterUsedBytes_start = PageAllocator::GetProcessUsedBytes();
129-
this->lastPassStats->isInScript = this->recycler->GetIsInScript();
130-
this->lastPassStats->isScriptActive = this->recycler->GetIsScriptActive();
131-
132-
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerLeafPageAllocator(), &this->lastPassStats->threadPageAllocator_start);
133-
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerPageAllocator(), &this->lastPassStats->recyclerLeafPageAllocator_start);
134-
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerLargeBlockPageAllocator(), &this->lastPassStats->recyclerLargeBlockPageAllocator_start);
108+
this->inPassActiveState = true;
109+
passCount++;
110+
memset(p, 0, sizeof(RecyclerTelemetryGCPassStats));
111+
if (this->lastPassStats == nullptr)
112+
{
113+
p->next = p;
114+
}
115+
else
116+
{
117+
p->next = lastPassStats->next;
118+
this->lastPassStats->next = p;
119+
}
120+
this->lastPassStats = p;
121+
122+
this->lastPassStats->isGCPassActive = true;
123+
this->lastPassStats->passStartTimeTick = Js::Tick::Now();
124+
GetSystemTimePreciseAsFileTime(&this->lastPassStats->passStartTimeFileTime);
125+
if (this->hostInterface != nullptr)
126+
{
127+
LPFILETIME ft = this->hostInterface->GetLastScriptExecutionEndTime();
128+
this->lastPassStats->lastScriptExecutionEndTime = *ft;
129+
}
130+
131+
this->lastPassStats->processCommittedBytes_start = RecyclerTelemetryInfo::GetProcessCommittedBytes();
132+
this->lastPassStats->processAllocaterUsedBytes_start = PageAllocator::GetProcessUsedBytes();
133+
this->lastPassStats->isInScript = this->recycler->GetIsInScript();
134+
this->lastPassStats->isScriptActive = this->recycler->GetIsScriptActive();
135+
136+
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerLeafPageAllocator(), &this->lastPassStats->threadPageAllocator_start);
137+
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerPageAllocator(), &this->lastPassStats->recyclerLeafPageAllocator_start);
138+
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerLargeBlockPageAllocator(), &this->lastPassStats->recyclerLargeBlockPageAllocator_start);
135139
#ifdef RECYCLER_WRITE_BARRIER_ALLOC_SEPARATE_PAGE
136-
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerWithBarrierPageAllocator(), &this->lastPassStats->recyclerWithBarrierPageAllocator_start);
140+
this->FillInSizeData(this->recycler->GetHeapInfo()->GetRecyclerWithBarrierPageAllocator(), &this->lastPassStats->recyclerWithBarrierPageAllocator_start);
137141
#endif
138-
this->lastPassStats->startPassProcessingElapsedTime = Js::Tick::Now() - start;
139-
}
140-
142+
this->lastPassStats->startPassProcessingElapsedTime = Js::Tick::Now() - start;
143+
}
141144

145+
}
142146
}
143147

144148
void RecyclerTelemetryInfo::EndPass()
145149
{
146-
if (!this->ShouldCaptureRecyclerTelemetry())
150+
if (!this->inPassActiveState)
147151
{
148152
return;
149153
}
154+
this->inPassActiveState = false;
150155

151156
Js::Tick start = Js::Tick::Now();
152157

@@ -220,7 +225,7 @@ namespace Memory
220225
}
221226
}
222227

223-
bool RecyclerTelemetryInfo::ShouldTransmit()
228+
bool RecyclerTelemetryInfo::ShouldTransmit() const
224229
{
225230
// for now, try to transmit telemetry when we have >= 16
226231
return (this->hostInterface != nullptr && this->passCount >= 16);
@@ -229,13 +234,13 @@ namespace Memory
229234
void RecyclerTelemetryInfo::IncrementUserThreadBlockedCount(Js::TickDelta waitTime, RecyclerWaitReason caller)
230235
{
231236
#ifdef DBG
232-
if (this->ShouldCaptureRecyclerTelemetry())
237+
if (this->inPassActiveState)
233238
{
234239
AssertMsg(this->lastPassStats != nullptr && this->lastPassStats->isGCPassActive == true, "unexpected Value in RecyclerTelemetryInfo::IncrementUserThreadBlockedCount");
235240
}
236241
#endif
237242

238-
if (this->ShouldCaptureRecyclerTelemetry() && this->lastPassStats != nullptr)
243+
if (this->inPassActiveState && this->lastPassStats != nullptr)
239244
{
240245
AssertOnValidThread(this, RecyclerTelemetryInfo::IncrementUserThreadBlockedCount);
241246
this->lastPassStats->uiThreadBlockedTimes[caller] += waitTime;

lib/Common/Memory/RecyclerTelemetryInfo.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace Memory
2828
virtual LPFILETIME GetLastScriptExecutionEndTime() const = 0;
2929
virtual bool TransmitTelemetry(RecyclerTelemetryInfo& rti) = 0;
3030
virtual bool TransmitTelemetryError(const RecyclerTelemetryInfo& rti, const char* msg) = 0;
31+
virtual bool IsTelemetryProviderEnabled() const = 0;
3132
virtual bool IsThreadBound() const = 0;
3233
virtual DWORD GetCurrentScriptThreadID() const = 0;
3334
};
@@ -94,7 +95,6 @@ namespace Memory
9495
inline const uint16 GetPassCount() const { return this->passCount; }
9596
const GUID& GetRecyclerID() const;
9697
bool GetIsConcurrentEnabled() const;
97-
bool ShouldCaptureRecyclerTelemetry() const;
9898
bool IsOnScriptThread() const;
9999

100100
AllocatorDecommitStats* GetThreadPageAllocator_decommitStats() { return &this->threadPageAllocator_decommitStats; }
@@ -109,6 +109,7 @@ namespace Memory
109109
DWORD mainThreadID;
110110
RecyclerTelemetryHostInterface * hostInterface;
111111
Js::Tick recyclerStartTime;
112+
bool inPassActiveState;
112113

113114
// TODO: update list below to SList. Need to ensure we have same allocation semantics (specifically heap allocs, no exceptions on failure)
114115
RecyclerTelemetryGCPassStats* lastPassStats;
@@ -123,7 +124,8 @@ namespace Memory
123124
AllocatorDecommitStats recyclerWithBarrierPageAllocator_decommitStats;
124125
#endif
125126

126-
bool ShouldTransmit();
127+
bool ShouldStartTelemetryCapture() const;
128+
bool ShouldTransmit() const;
127129
void FreeGCPassStats();
128130
void Reset();
129131
void FillInSizeData(IdleDecommitPageAllocator* allocator, AllocatorSizes* sizes) const;

lib/Runtime/Base/ThreadContext.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,16 @@ bool ThreadContext::ThreadContextRecyclerTelemetryHostInterface::TransmitTelemet
682682
#endif
683683
}
684684

685+
686+
bool ThreadContext::ThreadContextRecyclerTelemetryHostInterface::IsTelemetryProviderEnabled() const
687+
{
688+
#if defined(ENABLE_BASIC_TELEMETRY) && defined(NTBUILD)
689+
return Js::IsTelemetryProviderEnabled();
690+
#else
691+
return false;
692+
#endif
693+
}
694+
685695
bool ThreadContext::ThreadContextRecyclerTelemetryHostInterface::TransmitTelemetryError(const RecyclerTelemetryInfo& rti, const char * msg)
686696
{
687697
#if defined(ENABLE_BASIC_TELEMETRY) && defined(NTBUILD)

lib/Runtime/Base/ThreadContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,7 @@ class ThreadContext sealed :
18421842
virtual bool TransmitTelemetryError(const RecyclerTelemetryInfo& rti, const char * msg);
18431843
virtual bool ThreadContextRecyclerTelemetryHostInterface::IsThreadBound() const;
18441844
virtual DWORD ThreadContextRecyclerTelemetryHostInterface::GetCurrentScriptThreadID() const;
1845+
virtual bool IsTelemetryProviderEnabled() const;
18451846

18461847
private:
18471848
ThreadContext * tc;

0 commit comments

Comments
 (0)