@@ -73,52 +73,71 @@ class StackMeasurer_c
7373public:
7474 ATTRIBUTE_NO_SANITIZE_ADDRESS StackSizeTuplet_t MockMeasureStack ()
7575 {
76- constexpr int iMeasures = 20 ;
77- std::vector<std::pair<int ,DWORD>> dMeasures { iMeasures };
78- int i = 0 ;
79-
80- int iDepth = 0 ;
81- DWORD uStack = 0 ;
76+ constexpr int iMeasures = 50 ;
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 , DWORD>> dDeltas { iMeasures };
100- sphLogDebugv ( " ========= start measure ==============" );
101- std::pair<int ,DWORD> 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- uStack = 0 ;
113- for ( i=iValues-1 ; i>0 ; --i )
114- {
115- if ( dDeltas[i].first !=1 )
116- break ;
117- uStack = Max ( uStack, dDeltas[i].second );
118- }
136+ auto iStack = dHistogram.First ().first ;
137+ assert (iStack>0 );
119138
120- int iDelta = sphRoundUp ( uStack , 8 );
121- return { iStart , iDelta };
139+ int iDelta = sphRoundUp ( iStack , 8 );
140+ return { ( int )uStartingStack , iDelta };
122141 }
123142
124143 virtual ~StackMeasurer_c () = default ;
@@ -131,10 +150,17 @@ class CreateExprStackSize_c final : public StackMeasurer_c
131150 void BuildMockExpr ( int iComplexity ) final
132151 {
133152 m_sExpr.Clear ();
134- m_sExpr << " (( attr_a=0)*1) " ;
153+ m_sExpr << " IF( attr_a IN(0,1),10, " ;
135154
136- for ( int i = 1 ; i<iComplexity+1 ; ++i ) // ((attr_a=0)*1) + ((attr_b=1)*3) + ((attr_b=2)*5) + ...
137- m_sExpr << " +((attr_b=" << i << " )*" << i * 2 +1 << " )" ;
155+ for ( int i = 1 ; i<iComplexity+1 ; ++i )
156+ m_sExpr << " IF(attr_a IN(" << i << " ," << i+1 << " )," << (i+1 )*10 << " ," ;
157+ m_sExpr << (iComplexity+2 )*10 << " )" ;
158+ for ( int i = 0 ; i<iComplexity; ++i )
159+ m_sExpr << " )" ;
160+
161+ // IF(a IN(0,1),10,20)
162+ // IF(a IN(0,1),10,IF(a IN(1,2),20,30))
163+ // IF(a IN(0,1),10,IF(a IN(1,2),20,IF(a IN(2,3),30,40))) ...
138164 }
139165
140166 ATTRIBUTE_NO_SANITIZE_ADDRESS void MockParseTest () final
@@ -153,8 +179,6 @@ class CreateExprStackSize_c final : public StackMeasurer_c
153179 tAttr.m_eAttrType = SPH_ATTR_INTEGER;
154180 tAttr.m_sName = " attr_a" ;
155181 tParams.m_tSchema .AddAttr ( tAttr, false );
156- tAttr.m_sName = " attr_b" ;
157- tParams.m_tSchema .AddAttr ( tAttr, false );
158182
159183 tParams.m_sExpr = m_sExpr.cstr ();
160184
0 commit comments