1+ #include " collector_counters.h"
2+
3+ namespace NActors {
4+
5+ // THistogramCounters
6+
7+ void THistogramCounters::Init (NMonitoring::TDynamicCounters* group, const TString& baseName, const TString& unit, ui64 maxVal) {
8+ for (size_t i = 0 ; (1ull <<i) <= maxVal; ++i) {
9+ TString bucketName = ToString (1ull <<i) + " " + unit;
10+ Buckets.push_back (group->GetSubgroup (" sensor" , baseName)->GetNamedCounter (" range" , bucketName, true ));
11+ }
12+ Buckets.push_back (group->GetSubgroup (" sensor" , baseName)->GetNamedCounter (" range" , " INF" , true ));
13+ }
14+
15+ void THistogramCounters::Set (const TLogHistogram& data) {
16+ ui32 i = 0 ;
17+ for (;i < Y_ARRAY_SIZE (data.Buckets ) && i < Buckets.size ()-1 ; ++i)
18+ *Buckets[i] = data.Buckets [i];
19+ ui64 last = 0 ;
20+ for (;i < Y_ARRAY_SIZE (data.Buckets ); ++i)
21+ last += data.Buckets [i];
22+ *Buckets.back () = last;
23+ }
24+
25+ void THistogramCounters::Set (const TLogHistogram& data, double factor) {
26+ ui32 i = 0 ;
27+ for (;i < Y_ARRAY_SIZE (data.Buckets ) && i < Buckets.size ()-1 ; ++i)
28+ *Buckets[i] = data.Buckets [i]*factor;
29+ ui64 last = 0 ;
30+ for (;i < Y_ARRAY_SIZE (data.Buckets ); ++i)
31+ last += data.Buckets [i];
32+ *Buckets.back () = last*factor;
33+ }
34+
35+ // TActivityStats
36+
37+ void TActivityStats::Init (NMonitoring::TDynamicCounterPtr group) {
38+ Group = group;
39+
40+ CurrentActivationTimeByActivity.resize (GetActivityTypeCount ());
41+ ElapsedMicrosecByActivityBuckets.resize (GetActivityTypeCount ());
42+ ReceivedEventsByActivityBuckets.resize (GetActivityTypeCount ());
43+ ActorsAliveByActivityBuckets.resize (GetActivityTypeCount ());
44+ ScheduledEventsByActivityBuckets.resize (GetActivityTypeCount ());
45+ StuckActorsByActivityBuckets.resize (GetActivityTypeCount ());
46+ UsageByActivityBuckets.resize (GetActivityTypeCount ());
47+ }
48+
49+ void TActivityStats::Set (const TExecutorThreadStats& stats) {
50+ for (ui32 i : xrange (stats.MaxActivityType ())) {
51+ Y_ABORT_UNLESS (i < GetActivityTypeCount ());
52+ ui64 ticks = stats.ElapsedTicksByActivity [i];
53+ ui64 events = stats.ReceivedEventsByActivity [i];
54+ ui64 actors = stats.ActorsAliveByActivity [i];
55+ ui64 scheduled = stats.ScheduledEventsByActivity [i];
56+ ui64 stuck = stats.StuckActorsByActivity [i];
57+
58+ if (!ActorsAliveByActivityBuckets[i]) {
59+ if (ticks || events || actors || scheduled) {
60+ InitCountersForActivity (i);
61+ } else {
62+ continue ;
63+ }
64+ }
65+
66+ *CurrentActivationTimeByActivity[i] = 0 ;
67+ *ElapsedMicrosecByActivityBuckets[i] = ::NHPTimer::GetSeconds (ticks)*1000000 ;
68+ *ReceivedEventsByActivityBuckets[i] = events;
69+ *ActorsAliveByActivityBuckets[i] = actors;
70+ *ScheduledEventsByActivityBuckets[i] = scheduled;
71+ *StuckActorsByActivityBuckets[i] = stuck;
72+
73+ for (ui32 j = 0 ; j < 10 ; ++j) {
74+ *UsageByActivityBuckets[i][j] = stats.UsageByActivity [i][j];
75+ }
76+ }
77+
78+ auto setActivationTime = [&](TActivationTime activation) {
79+ if (!ActorsAliveByActivityBuckets[activation.LastActivity ]) {
80+ InitCountersForActivity (activation.LastActivity );
81+ }
82+ *CurrentActivationTimeByActivity[activation.LastActivity ] = activation.TimeUs ;
83+ };
84+ if (stats.CurrentActivationTime .TimeUs ) {
85+ setActivationTime (stats.CurrentActivationTime );
86+ }
87+ std::vector<TActivationTime> activationTimes = stats.AggregatedCurrentActivationTime ;
88+ Sort (activationTimes.begin (), activationTimes.end (), [](auto &left, auto &right) {
89+ return left.LastActivity < right.LastActivity ||
90+ left.LastActivity == right.LastActivity && left.TimeUs > right.TimeUs ;
91+ });
92+ ui32 prevActivity = Max<ui32>();
93+ for (auto &activationTime : activationTimes) {
94+ if (activationTime.LastActivity == prevActivity) {
95+ continue ;
96+ }
97+ setActivationTime (activationTime);
98+ prevActivity = activationTime.LastActivity ;
99+ }
100+ }
101+
102+ void TActivityStats::InitCountersForActivity (ui32 activityType) {
103+ Y_ABORT_UNLESS (activityType < GetActivityTypeCount ());
104+
105+ auto bucketName = TString (GetActivityTypeName (activityType));
106+
107+ CurrentActivationTimeByActivity[activityType] =
108+ Group->GetSubgroup (" sensor" , " CurrentActivationTimeUsByActivity" )->GetNamedCounter (" activity" , bucketName, false );
109+ ElapsedMicrosecByActivityBuckets[activityType] =
110+ Group->GetSubgroup (" sensor" , " ElapsedMicrosecByActivity" )->GetNamedCounter (" activity" , bucketName, true );
111+ ReceivedEventsByActivityBuckets[activityType] =
112+ Group->GetSubgroup (" sensor" , " ReceivedEventsByActivity" )->GetNamedCounter (" activity" , bucketName, true );
113+ ActorsAliveByActivityBuckets[activityType] =
114+ Group->GetSubgroup (" sensor" , " ActorsAliveByActivity" )->GetNamedCounter (" activity" , bucketName, false );
115+ ScheduledEventsByActivityBuckets[activityType] =
116+ Group->GetSubgroup (" sensor" , " ScheduledEventsByActivity" )->GetNamedCounter (" activity" , bucketName, true );
117+ StuckActorsByActivityBuckets[activityType] =
118+ Group->GetSubgroup (" sensor" , " StuckActorsByActivity" )->GetNamedCounter (" activity" , bucketName, false );
119+
120+ for (ui32 i = 0 ; i < 10 ; ++i) {
121+ UsageByActivityBuckets[activityType][i] = Group->GetSubgroup (" sensor" , " UsageByActivity" )->GetSubgroup (" bin" , ToString (i))->GetNamedCounter (" activity" , bucketName, false );
122+ }
123+ }
124+
125+ // TExecutorPoolCounters
126+
127+ void TExecutorPoolCounters::Init (NMonitoring::TDynamicCounters* group, const TString& poolName, ui32 threads) {
128+ LastElapsedSeconds = 0 ;
129+ Usage = 0 ;
130+ UsageTimer.Reset ();
131+ Name = poolName;
132+ Threads = threads;
133+ LimitThreads = threads;
134+ DefaultThreads = threads;
135+
136+ PoolGroup = group->GetSubgroup (" execpool" , poolName);
137+
138+ SentEvents = PoolGroup->GetCounter (" SentEvents" , true );
139+ ReceivedEvents = PoolGroup->GetCounter (" ReceivedEvents" , true );
140+ PreemptedEvents = PoolGroup->GetCounter (" PreemptedEvents" , true );
141+ NonDeliveredEvents = PoolGroup->GetCounter (" NonDeliveredEvents" , true );
142+ DestroyedActors = PoolGroup->GetCounter (" DestroyedActors" , true );
143+ CpuMicrosec = PoolGroup->GetCounter (" CpuMicrosec" , true );
144+ ElapsedMicrosec = PoolGroup->GetCounter (" ElapsedMicrosec" , true );
145+ ParkedMicrosec = PoolGroup->GetCounter (" ParkedMicrosec" , true );
146+ EmptyMailboxActivation = PoolGroup->GetCounter (" EmptyMailboxActivation" , true );
147+ ActorRegistrations = PoolGroup->GetCounter (" ActorRegistrations" , true );
148+ ActorsAlive = PoolGroup->GetCounter (" ActorsAlive" , false );
149+ AllocatedMailboxes = PoolGroup->GetCounter (" AllocatedMailboxes" , false );
150+ MailboxPushedOutBySoftPreemption = PoolGroup->GetCounter (" MailboxPushedOutBySoftPreemption" , true );
151+ MailboxPushedOutByTime = PoolGroup->GetCounter (" MailboxPushedOutByTime" , true );
152+ MailboxPushedOutByEventCount = PoolGroup->GetCounter (" MailboxPushedOutByEventCount" , true );
153+ WrongWakenedThreadCount = PoolGroup->GetCounter (" WrongWakenedThreadCount" , true );
154+ CurrentThreadCount = PoolGroup->GetCounter (" CurrentThreadCount" , false );
155+ PotentialMaxThreadCount = PoolGroup->GetCounter (" PotentialMaxThreadCount" , false );
156+ DefaultThreadCount = PoolGroup->GetCounter (" DefaultThreadCount" , false );
157+ MaxThreadCount = PoolGroup->GetCounter (" MaxThreadCount" , false );
158+
159+ CurrentThreadCountPercent = PoolGroup->GetCounter (" CurrentThreadCountPercent" , false );
160+ PotentialMaxThreadCountPercent = PoolGroup->GetCounter (" PotentialMaxThreadCountPercent" , false );
161+ PossibleMaxThreadCountPercent = PoolGroup->GetCounter (" PossibleMaxThreadCountPercent" , false );
162+ DefaultThreadCountPercent = PoolGroup->GetCounter (" DefaultThreadCountPercent" , false );
163+ MaxThreadCountPercent = PoolGroup->GetCounter (" MaxThreadCountPercent" , false );
164+
165+ IsNeedy = PoolGroup->GetCounter (" IsNeedy" , false );
166+ IsStarved = PoolGroup->GetCounter (" IsStarved" , false );
167+ IsHoggish = PoolGroup->GetCounter (" IsHoggish" , false );
168+ HasFullOwnSharedThread = PoolGroup->GetCounter (" HasFullOwnSharedThread" , false );
169+ HasHalfOfOwnSharedThread = PoolGroup->GetCounter (" HasHalfOfOwnSharedThread" , false );
170+ HasHalfOfOtherSharedThread = PoolGroup->GetCounter (" HasHalfOfOtherSharedThread" , false );
171+ IncreasingThreadsByNeedyState = PoolGroup->GetCounter (" IncreasingThreadsByNeedyState" , true );
172+ IncreasingThreadsByExchange = PoolGroup->GetCounter (" IncreasingThreadsByExchange" , true );
173+ DecreasingThreadsByStarvedState = PoolGroup->GetCounter (" DecreasingThreadsByStarvedState" , true );
174+ DecreasingThreadsByHoggishState = PoolGroup->GetCounter (" DecreasingThreadsByHoggishState" , true );
175+ DecreasingThreadsByExchange = PoolGroup->GetCounter (" DecreasingThreadsByExchange" , true );
176+ NotEnoughCpuExecutions = PoolGroup->GetCounter (" NotEnoughCpuExecutions" , true );
177+ SpinningTimeUs = PoolGroup->GetCounter (" SpinningTimeUs" , true );
178+ SpinThresholdUs = PoolGroup->GetCounter (" SpinThresholdUs" , false );
179+
180+
181+ LegacyActivationTimeHistogram.Init (PoolGroup.Get (), " ActivationTime" , " usec" , 5 *1000 *1000 );
182+ ActivationTimeHistogram = PoolGroup->GetHistogram (
183+ " ActivationTimeUs" , NMonitoring::ExponentialHistogram (24 , 2 , 1 ));
184+ LegacyEventDeliveryTimeHistogram.Init (PoolGroup.Get (), " EventDeliveryTime" , " usec" , 5 *1000 *1000 );
185+ EventDeliveryTimeHistogram = PoolGroup->GetHistogram (
186+ " EventDeliveryTimeUs" , NMonitoring::ExponentialHistogram (24 , 2 , 1 ));
187+ LegacyEventProcessingCountHistogram.Init (PoolGroup.Get (), " EventProcessingCount" , " usec" , 5 *1000 *1000 );
188+ EventProcessingCountHistogram = PoolGroup->GetHistogram (
189+ " EventProcessingCountUs" , NMonitoring::ExponentialHistogram (24 , 2 , 1 ));
190+ LegacyEventProcessingTimeHistogram.Init (PoolGroup.Get (), " EventProcessingTime" , " usec" , 5 *1000 *1000 );
191+ EventProcessingTimeHistogram = PoolGroup->GetHistogram (
192+ " EventProcessingTimeUs" , NMonitoring::ExponentialHistogram (24 , 2 , 1 ));
193+
194+ ActivityStats.Init (PoolGroup.Get ());
195+
196+ MaxUtilizationTime = PoolGroup->GetCounter (" MaxUtilizationTime" , true );
197+ }
198+
199+ void TExecutorPoolCounters::Set (const TExecutorPoolStats& poolStats, const TExecutorThreadStats& stats) {
200+ #ifdef ACTORSLIB_COLLECT_EXEC_STATS
201+ double elapsedSeconds = ::NHPTimer::GetSeconds (stats.ElapsedTicks );
202+ *SentEvents = stats.SentEvents ;
203+ *ReceivedEvents = stats.ReceivedEvents ;
204+ *PreemptedEvents = stats.PreemptedEvents ;
205+ *NonDeliveredEvents = stats.NonDeliveredEvents ;
206+ *DestroyedActors = stats.PoolDestroyedActors ;
207+ *EmptyMailboxActivation = stats.EmptyMailboxActivation ;
208+ *CpuMicrosec = stats.CpuUs ;
209+ *ElapsedMicrosec = elapsedSeconds*1000000 ;
210+ *ParkedMicrosec = ::NHPTimer::GetSeconds (stats.ParkedTicks )*1000000 ;
211+ *ActorRegistrations = stats.PoolActorRegistrations ;
212+ *ActorsAlive = stats.PoolActorRegistrations - stats.PoolDestroyedActors ;
213+ *AllocatedMailboxes = stats.PoolAllocatedMailboxes ;
214+ *MailboxPushedOutBySoftPreemption = stats.MailboxPushedOutBySoftPreemption ;
215+ *MailboxPushedOutByTime = stats.MailboxPushedOutByTime ;
216+ *MailboxPushedOutByEventCount = stats.MailboxPushedOutByEventCount ;
217+ *WrongWakenedThreadCount = poolStats.WrongWakenedThreadCount ;
218+ *CurrentThreadCount = poolStats.CurrentThreadCount ;
219+ *PotentialMaxThreadCount = poolStats.PotentialMaxThreadCount ;
220+ *DefaultThreadCount = poolStats.DefaultThreadCount ;
221+ *MaxThreadCount = poolStats.MaxThreadCount ;
222+
223+ *CurrentThreadCountPercent = poolStats.CurrentThreadCount * 100 ;
224+ *PotentialMaxThreadCountPercent = poolStats.PotentialMaxThreadCount * 100 ;
225+ *PossibleMaxThreadCountPercent = poolStats.PotentialMaxThreadCount * 100 ;
226+ *DefaultThreadCountPercent = poolStats.DefaultThreadCount * 100 ;
227+ *MaxThreadCountPercent = poolStats.MaxThreadCount * 100 ;
228+
229+ *IsNeedy = poolStats.IsNeedy ;
230+ *IsStarved = poolStats.IsStarved ;
231+ *IsHoggish = poolStats.IsHoggish ;
232+
233+ *HasFullOwnSharedThread = poolStats.HasFullOwnSharedThread ;
234+ *HasHalfOfOwnSharedThread = poolStats.HasHalfOfOwnSharedThread ;
235+ *HasHalfOfOtherSharedThread = poolStats.HasHalfOfOtherSharedThread ;
236+ *IncreasingThreadsByNeedyState = poolStats.IncreasingThreadsByNeedyState ;
237+ *IncreasingThreadsByExchange = poolStats.IncreasingThreadsByExchange ;
238+ *DecreasingThreadsByStarvedState = poolStats.DecreasingThreadsByStarvedState ;
239+ *DecreasingThreadsByHoggishState = poolStats.DecreasingThreadsByHoggishState ;
240+ *DecreasingThreadsByExchange = poolStats.DecreasingThreadsByExchange ;
241+ *NotEnoughCpuExecutions = stats.NotEnoughCpuExecutions ;
242+
243+ *SpinningTimeUs = poolStats.SpinningTimeUs ;
244+ *SpinThresholdUs = poolStats.SpinThresholdUs ;
245+
246+ LegacyActivationTimeHistogram.Set (stats.ActivationTimeHistogram );
247+ ActivationTimeHistogram->Reset ();
248+ ActivationTimeHistogram->Collect (stats.ActivationTimeHistogram );
249+
250+ LegacyEventDeliveryTimeHistogram.Set (stats.EventDeliveryTimeHistogram );
251+ EventDeliveryTimeHistogram->Reset ();
252+ EventDeliveryTimeHistogram->Collect (stats.EventDeliveryTimeHistogram );
253+
254+ LegacyEventProcessingCountHistogram.Set (stats.EventProcessingCountHistogram );
255+ EventProcessingCountHistogram->Reset ();
256+ EventProcessingCountHistogram->Collect (stats.EventProcessingCountHistogram );
257+
258+ double toMicrosec = 1000000 / NHPTimer::GetClockRate ();
259+ LegacyEventProcessingTimeHistogram.Set (stats.EventProcessingTimeHistogram , toMicrosec);
260+ EventProcessingTimeHistogram->Reset ();
261+ for (ui32 i = 0 ; i < stats.EventProcessingTimeHistogram .Count (); ++i) {
262+ EventProcessingTimeHistogram->Collect (
263+ stats.EventProcessingTimeHistogram .UpperBound (i),
264+ stats.EventProcessingTimeHistogram .Value (i) * toMicrosec);
265+ }
266+
267+ ActivityStats.Set (stats);
268+
269+ *MaxUtilizationTime = poolStats.MaxUtilizationTime ;
270+
271+ double seconds = UsageTimer.PassedReset ();
272+
273+ // TODO[serxa]: It doesn't account for contention. Use 1 - parkedTicksDelta / seconds / numThreads KIKIMR-11916
274+ Threads = poolStats.CurrentThreadCount ;
275+ LimitThreads = poolStats.PotentialMaxThreadCount ;
276+ const double currentUsage = LimitThreads > 0 ? ((elapsedSeconds - LastElapsedSeconds) / seconds / LimitThreads) : 0 ;
277+
278+ // update usage factor according to smoothness
279+ const double smoothness = 0.5 ;
280+ Usage = currentUsage * smoothness + Usage * (1.0 - smoothness);
281+ LastElapsedSeconds = elapsedSeconds;
282+ #else
283+ Y_UNUSED (stats);
284+ Y_UNUSED (poolStats);
285+ #endif
286+ }
287+
288+ // TActorSystemCounters
289+
290+ void TActorSystemCounters::Init (NMonitoring::TDynamicCounters* group) {
291+ Group = group;
292+
293+ MaxUsedCpuPercent = Group->GetCounter (" MaxUsedCpuPercent" , false );
294+ MinUsedCpuPercent = Group->GetCounter (" MinUsedCpuPercent" , false );
295+ MaxElapsedCpuPercent = Group->GetCounter (" MaxElapsedCpuPercent" , false );
296+ MinElapsedCpuPercent = Group->GetCounter (" MinElapsedCpuPercent" , false );
297+ AvgAwakeningTimeNs = Group->GetCounter (" AvgAwakeningTimeNs" , false );
298+ AvgWakingUpTimeNs = Group->GetCounter (" AvgWakingUpTimeNs" , false );
299+ }
300+
301+ void TActorSystemCounters::Set (const THarmonizerStats& harmonizerStats) {
302+ #ifdef ACTORSLIB_COLLECT_EXEC_STATS
303+ *MaxUsedCpuPercent = harmonizerStats.MaxUsedCpu ;
304+ *MinUsedCpuPercent = harmonizerStats.MinUsedCpu ;
305+ *MaxElapsedCpuPercent = harmonizerStats.MaxElapsedCpu ;
306+ *MinElapsedCpuPercent = harmonizerStats.MinElapsedCpu ;
307+
308+ *AvgAwakeningTimeNs = harmonizerStats.AvgAwakeningTimeUs * 1000 ;
309+ *AvgWakingUpTimeNs = harmonizerStats.AvgWakingUpTimeUs * 1000 ;
310+ #else
311+ Y_UNUSED (harmonizerStats);
312+ #endif
313+ }
314+
315+ } // NActors
0 commit comments