@@ -14,6 +14,8 @@ void TCpuConsumptionInfo::Clear() {
14
14
15
15
void THarmonizerCpuConsumption::Init (i16 poolCount) {
16
16
PoolConsumption.resize (poolCount);
17
+ PoolFullThreadConsumption.resize (poolCount);
18
+ PoolForeignConsumption.resize (poolCount);
17
19
IsNeedyByPool.reserve (poolCount);
18
20
NeedyPools.reserve (poolCount);
19
21
HoggishPools.reserve (poolCount);
@@ -25,8 +27,9 @@ namespace {
25
27
return Max (0.0 , Min (1.0 , value * (1.0 /0.9 )));
26
28
}
27
29
28
- void UpdatePoolConsumption (const TPoolInfo& pool, TCpuConsumptionInfo *poolConsumption) {
30
+ void UpdatePoolConsumption (const TPoolInfo& pool, TCpuConsumptionInfo *poolConsumption, TCpuConsumptionInfo *poolFullThreadConsumption ) {
29
31
poolConsumption->Clear ();
32
+ poolFullThreadConsumption->Clear ();
30
33
for (i16 threadIdx = 0 ; threadIdx < pool.MaxThreadCount ; ++threadIdx) {
31
34
float threadElapsed = Rescale (pool.GetElapsed (threadIdx));
32
35
float threadLastSecondElapsed = Rescale (pool.GetLastSecondElapsed (threadIdx));
@@ -36,13 +39,17 @@ namespace {
36
39
poolConsumption->LastSecondElapsed += threadLastSecondElapsed;
37
40
poolConsumption->Cpu += threadCpu;
38
41
poolConsumption->LastSecondCpu += threadLastSecondCpu;
42
+ poolFullThreadConsumption->Elapsed += threadElapsed;
43
+ poolFullThreadConsumption->LastSecondElapsed += threadLastSecondElapsed;
44
+ poolFullThreadConsumption->Cpu += threadCpu;
45
+ poolFullThreadConsumption->LastSecondCpu += threadLastSecondCpu;
39
46
LWPROBE_WITH_DEBUG (HarmonizeCheckPoolByThread, pool.Pool ->PoolId , pool.Pool ->GetName (), threadIdx, threadElapsed, threadCpu, threadLastSecondElapsed, threadLastSecondCpu);
40
47
}
41
48
for (i16 sharedIdx = 0 ; sharedIdx < static_cast <i16 >(pool.SharedInfo .size ()); ++sharedIdx) {
42
- float sharedElapsed = Rescale ( pool.GetSharedElapsed (sharedIdx) );
43
- float sharedLastSecondElapsed = Rescale ( pool.GetLastSecondSharedElapsed (sharedIdx) );
44
- float sharedCpu = Rescale ( pool.GetSharedCpu (sharedIdx) );
45
- float sharedLastSecondCpu = Rescale ( pool.GetLastSecondSharedCpu (sharedIdx) );
49
+ float sharedElapsed = pool.GetSharedElapsed (sharedIdx);
50
+ float sharedLastSecondElapsed = pool.GetLastSecondSharedElapsed (sharedIdx);
51
+ float sharedCpu = pool.GetSharedCpu (sharedIdx);
52
+ float sharedLastSecondCpu = pool.GetLastSecondSharedCpu (sharedIdx);
46
53
poolConsumption->Elapsed += sharedElapsed;
47
54
poolConsumption->LastSecondElapsed += sharedLastSecondElapsed;
48
55
poolConsumption->Cpu += sharedCpu;
@@ -51,12 +58,19 @@ namespace {
51
58
}
52
59
}
53
60
61
+ void UpdatePoolForeignConsumption (const TPoolInfo& pool, TPoolForeignConsumptionInfo *poolForeignConsumption, const TSharedInfo& sharedInfo) {
62
+ float prevElapsed = std::exchange (poolForeignConsumption->PrevElapsedValue , sharedInfo.CpuConsumption [pool.Pool ->PoolId ].ForeignElapsed );
63
+ float prevCpu = std::exchange (poolForeignConsumption->PrevCpuValue , sharedInfo.CpuConsumption [pool.Pool ->PoolId ].ForeignCpu );
64
+ poolForeignConsumption->Elapsed = sharedInfo.CpuConsumption [pool.Pool ->PoolId ].ForeignElapsed - prevElapsed;
65
+ poolForeignConsumption->Cpu = sharedInfo.CpuConsumption [pool.Pool ->PoolId ].ForeignCpu - prevCpu;
66
+ }
67
+
54
68
bool IsStarved (double elapsed, double cpu) {
55
69
return Max (elapsed, cpu) > 0.1 && (cpu < elapsed * 0.7 || elapsed - cpu > 0.5 );
56
70
}
57
71
58
72
bool IsHoggish (double elapsed, double currentThreadCount) {
59
- return elapsed < currentThreadCount - 0.5 ;
73
+ return elapsed <= currentThreadCount - 1.0 ;
60
74
}
61
75
62
76
} // namespace
@@ -82,34 +96,51 @@ void THarmonizerCpuConsumption::Pull(const std::vector<std::unique_ptr<TPoolInfo
82
96
83
97
AdditionalThreads += Max (0 , pool.GetFullThreadCount () - pool.DefaultFullThreadCount );
84
98
float currentThreadCount = pool.GetThreadCount ();
99
+ float currentFullThreadCount = pool.GetFullThreadCount ();
85
100
StoppingThreads += pool.Pool ->GetBlockingThreadCount ();
86
101
HARMONIZER_DEBUG_PRINT (" pool" , poolIdx, " pool name" , pool.Pool ->GetName (), " current thread count" , currentThreadCount, " stopping threads" , StoppingThreads, " default thread count" , pool.DefaultThreadCount );
87
102
88
- UpdatePoolConsumption (pool, &PoolConsumption[poolIdx]);
89
-
90
- HARMONIZER_DEBUG_PRINT (" pool" , poolIdx, " pool name" , pool.Pool ->GetName (), " elapsed" , PoolConsumption[poolIdx].Elapsed , " cpu" , PoolConsumption[poolIdx].Cpu , " last second elapsed" , PoolConsumption[poolIdx].LastSecondElapsed , " last second cpu" , PoolConsumption[poolIdx].LastSecondCpu );
103
+ UpdatePoolConsumption (pool, &PoolConsumption[poolIdx], &PoolFullThreadConsumption[poolIdx]);
104
+ UpdatePoolForeignConsumption (pool, &PoolForeignConsumption[poolIdx], sharedInfo);
105
+
106
+ HARMONIZER_DEBUG_PRINT (" CpuConsumption::Pull" ,
107
+ " pool:" , poolIdx,
108
+ " pool name:" , pool.Pool ->GetName (),
109
+ " elapsed:" , PoolConsumption[poolIdx].Elapsed ,
110
+ " cpu:" , PoolConsumption[poolIdx].Cpu ,
111
+ " last second elapsed:" , PoolConsumption[poolIdx].LastSecondElapsed ,
112
+ " last second cpu:" , PoolConsumption[poolIdx].LastSecondCpu ,
113
+ " full thread elapsed:" , PoolFullThreadConsumption[poolIdx].Elapsed ,
114
+ " full thread cpu:" , PoolFullThreadConsumption[poolIdx].Cpu ,
115
+ " last second full thread elapsed:" , PoolFullThreadConsumption[poolIdx].LastSecondElapsed ,
116
+ " last second full thread cpu:" , PoolFullThreadConsumption[poolIdx].LastSecondCpu ,
117
+ " foreign elapsed:" , PoolForeignConsumption[poolIdx].Elapsed ,
118
+ " foreign cpu:" , PoolForeignConsumption[poolIdx].Cpu
119
+ );
91
120
92
121
bool isStarved = IsStarved (PoolConsumption[poolIdx].Elapsed , PoolConsumption[poolIdx].Cpu )
93
122
|| IsStarved (PoolConsumption[poolIdx].LastSecondElapsed , PoolConsumption[poolIdx].LastSecondCpu );
94
123
if (isStarved) {
95
124
IsStarvedPresent = true ;
96
125
}
97
126
98
- bool isNeedy = (pool.IsAvgPingGood () || pool.NewNotEnoughCpuExecutions ) && (PoolConsumption[poolIdx].LastSecondCpu >= currentThreadCount);
127
+ float expectedThreadCount = pool.GetFullThreadCount () + (sharedInfo.OwnedThreads [poolIdx] != -1 ? 1 : 0 ) + 0.5 ;
128
+ bool isMoreThanExpected = (PoolConsumption[poolIdx].LastSecondCpu >= expectedThreadCount) && (PoolFullThreadConsumption[poolIdx].LastSecondCpu >= currentFullThreadCount - 1 );
129
+ bool isNeedy = (pool.IsAvgPingGood () || pool.NewNotEnoughCpuExecutions ) && (PoolConsumption[poolIdx].LastSecondCpu >= currentThreadCount || isMoreThanExpected);
99
130
IsNeedyByPool.push_back (isNeedy);
100
131
if (isNeedy) {
101
132
NeedyPools.push_back (poolIdx);
102
133
}
103
134
104
- bool isHoggish = IsHoggish (PoolConsumption [poolIdx].Elapsed , currentThreadCount );
135
+ bool isHoggish = !isNeedy && IsHoggish (PoolFullThreadConsumption [poolIdx].Elapsed , currentFullThreadCount) && IsHoggish (PoolFullThreadConsumption[poolIdx]. LastSecondElapsed , currentFullThreadCount );
105
136
if (isHoggish) {
106
- float freeCpu = currentThreadCount - PoolConsumption [poolIdx].Elapsed ;
137
+ float freeCpu = std::min (currentFullThreadCount - PoolFullThreadConsumption [poolIdx].Elapsed , currentFullThreadCount - PoolFullThreadConsumption[poolIdx]. LastSecondElapsed ) ;
107
138
HoggishPools.push_back ({poolIdx, freeCpu});
108
139
}
109
140
110
141
Elapsed += PoolConsumption[poolIdx].Elapsed ;
111
142
Cpu += PoolConsumption[poolIdx].Cpu ;
112
- LastSecondElapsed += PoolConsumption[poolIdx].LastSecondElapsed ;
143
+ LastSecondElapsed += PoolConsumption[poolIdx].LastSecondElapsed ;
113
144
LastSecondCpu += PoolConsumption[poolIdx].LastSecondCpu ;
114
145
pool.LastFlags .store ((i64 )isNeedy | ((i64 )isStarved << 1 ) | ((i64 )isHoggish << 2 ), std::memory_order_relaxed);
115
146
LWPROBE_WITH_DEBUG (
@@ -140,10 +171,12 @@ void THarmonizerCpuConsumption::Pull(const std::vector<std::unique_ptr<TPoolInfo
140
171
HARMONIZER_DEBUG_PRINT (" NeedyPools" , NeedyPools.size (), " HoggishPools" , HoggishPools.size ());
141
172
142
173
Budget = TotalCores - Elapsed;
174
+ BudgetLS = TotalCores - LastSecondElapsed;
143
175
BudgetWithoutSharedCpu = Budget - sharedInfo.FreeCpu ;
176
+ BudgetLSWithoutSharedCpu = BudgetLS - sharedInfo.FreeCpu ;
144
177
Overbooked = -Budget;
145
178
LostCpu = Max<float >(0 .0f , Elapsed - Cpu);
146
- if (Budget < -0.1 ) {
179
+ if (BudgetLS < -0.1 ) {
147
180
IsStarvedPresent = true ;
148
181
}
149
182
HARMONIZER_DEBUG_PRINT (" IsStarvedPresent" , IsStarvedPresent, " Budget" , Budget, " Overbooked" , Overbooked, " TotalCores" , TotalCores, " Elapsed" , Elapsed, " Cpu" , Cpu, " LastSecondElapsed" , LastSecondElapsed, " LastSecondCpu" , LastSecondCpu);
0 commit comments