Skip to content

Commit 84e7547

Browse files
author
Mike Kaufman
committed
only capturing recycler stats if telemetry provider is enabled. This will avoid extra work in most release scenarios where telemetry data is not being captured.
1 parent 362e541 commit 84e7547

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)