@@ -74,52 +74,70 @@ class StackMeasurer_c
7474 ATTRIBUTE_NO_SANITIZE_ADDRESS StackSizeTuplet_t MockMeasureStack ()
7575 {
7676 constexpr int iMeasures = 50 ;
77- std::vector<std::pair<int ,DWORD>> dMeasures { iMeasures };
78- int i = 0 ;
79-
80- int iDepth = 0 ;
81- DWORD uStack = 0 ;
77+ DWORD uDepth = 0 ;
78+ BuildMockExprWrapper ( uDepth );
79+ auto uStartingStack = MeasureStack ();
80+ sphLogDebugv ( " ========= start measure ==============" );
81+ sphLogDebugv ( " height 0, stack %d, deltah %d, deltastack %d" , uStartingStack, 0 , uStartingStack );
82+
83+ DWORD i = 1 ;
84+ CSphVector<std::pair<int ,int >> dHistogram;
85+ auto IncValue = [&dHistogram] ( int i ) {
86+ for ( auto & pair : dHistogram ) { // expected 2..5 elements; so linear search is perfect here.
87+ if ( pair.first != i )
88+ continue ;
89+ ++pair.second ;
90+ return pair.second ;
91+ }
92+ dHistogram.Add ({i,1 });
93+ return 1 ;
94+ };
95+ DWORD uPreviousStack = uStartingStack;
96+ DWORD uPreviousDepth = uDepth;
8297 while ( i<iMeasures )
8398 {
84- BuildMockExprWrapper ( iDepth++ );
99+ BuildMockExprWrapper ( ++uDepth );
85100 auto uThisStack = MeasureStack ();
86- if ( uThisStack == uStack )
101+ if ( uThisStack == uPreviousStack )
87102 continue ;
88103
89- dMeasures[i].first = iDepth-1 ;
90- dMeasures[i].second = uThisStack;
91- auto iDelta = uThisStack-uStack;
92- uStack = uThisStack;
104+ int iDelta = uThisStack - uPreviousStack;
105+ DWORD uDeltaDepth = uDepth - uPreviousDepth;
106+ uPreviousStack = uThisStack;
107+ uPreviousDepth = uDepth;
108+ sphLogDebugv ( " height %d, stack %d, deltah %d, deltastack %d" , uDepth, uThisStack, uDeltaDepth, iDelta );
93109 ++i;
94- if ( uStack + iDelta >= m_dMockStack.GetLengthBytes () )
110+ if ( uDeltaDepth==1 )
111+ {
112+ auto iMaxTries = IncValue ( iDelta );
113+ const auto iRestTries = iMeasures - i;
114+ if ( iMaxTries>iRestTries ) // we may stop here, if continuing will definitely give us nothing better
115+ {
116+ if ( dHistogram.GetLength ()==1 )
117+ break ;
118+ dHistogram.Sort ( Lesser ( [] ( auto l, auto r ) { return l.second >r.second ; } ) );
119+ assert (iMaxTries == dHistogram.First ().second );
120+ if ( iMaxTries > (iRestTries + dHistogram[1 ].second ) )
121+ break ;
122+ }
123+ }
124+ if ( uPreviousStack + iDelta >= m_dMockStack.GetLengthBytes () )
95125 break ;
96126 }
97127
98- auto iValues = i;
99- std::vector<std::pair<int , int >> dDeltas { iMeasures };
100- sphLogDebugv ( " ========= start measure ==============" );
101- std::pair<int ,int > dInitial {0 ,0 };
102- for ( i=0 ; i<iValues; ++i )
103- {
104- dDeltas[i].first = dMeasures[i].first -dInitial.first ;
105- dDeltas[i].second = dMeasures[i].second -dInitial.second ;
106- sphLogDebugv ( " height %d, stack %d, deltah %d, deltastack %d" , dMeasures[i].first , dMeasures[i].second , dDeltas[i].first , dDeltas[i].second );
107- dInitial = dMeasures[i];
108- }
128+ dHistogram.Sort ( Lesser ( [] ( auto l, auto r ) { return l.second >r.second ; } ) );
129+ sphLogDebugv ( " Performed %d measures out of %d, max depth %d" , i, iMeasures, uDepth );
130+ for ( const auto & pair : dHistogram )
131+ sphLogDebugv ( " stack frame size %d, frames %d" , pair.first , pair.second );
109132
110- int iStart = dMeasures.front ().second ;
133+ if ( dHistogram.IsEmpty () )
134+ sphWarning (" Something wrong measuring stack. After %d tries, %d depth" , i, uDepth );
111135
112- int iStack = 0 ;
113- for ( i=iValues-1 ; i>0 ; --i )
114- {
115- if ( dDeltas[i].first !=1 )
116- break ;
117- iStack = Max ( iStack, dDeltas[i].second );
118- }
136+ auto iStack = dHistogram.First ().first ;
119137 assert (iStack>0 );
120138
121139 int iDelta = sphRoundUp ( iStack, 8 );
122- return { iStart , iDelta };
140+ return { ( int )uStartingStack , iDelta };
123141 }
124142
125143 virtual ~StackMeasurer_c () = default ;
0 commit comments