My project deals with historical and real time data analysis. Contains several complex algorithms (over 800) at its last stage. Overall the analysis stages are roughly as follows:
- Basic formulas calculation->results storage
- Second stage formulas using above formulas->results storage
- Third stage formulas which decide upon desired action.
These third stage formulas are large blocks of complex conditionals. These complex conditionals though, use a finite number of simpler statements. And as a result these simpler statements get repeated a lot of times among the complex conditionals. Let me give you a greatly simplified example.
if ((var1[0]<var2[0]*0.5)and(var3[0]=1))or(var15[1]<>var15[0]))
....lots of similar statements....
then take action.
Now, Statements like
"(var3[0]=1)" or "(var15[1]<>var15[0])"
get used over and over again in other if blocks. My idea is to parse all these unique simple statements and automatically create some code that calculates their result (true/false) and stores them in an array of Boolean, once before Third stage commences. Like so:
arr[12]:=var1[0]<var2[0]*0.5;
arr[13]:=var3[0]=1;
...
arr[128]:=var15[1]<>var15[0];
Then (again by parsing my code before compiling) substitute the simpler statements with their corresponding array elements.
So, instead of
if ((var1[0]<var2[0]*0.5)and(var3[0]=1))or(var15[1]<>var15[0]))
it would look like
if ((arr[12])and(arr[13]))or(arr[128])
Would these changes in my code speed up my execution(calculation) time? Or the compiler already does something similar and I will just be wasting my time? Keep in mind that these simple statements get repeated tens or hundreds of times during each calculation cycle. And there is a minimum of 300,000 cycles to be calculated before real time data kick in. So, every little helps. In essence I am asking if a comparison between variables is slower than the retrieval of a Boolean array element’s value;
UPDATE
Since some people asked for some real code, here is one part of real code. 98% of code is variables (everything with [0] is a variable allowing access to previous variable values). 2% is functions. Variables are calculated in previous stage. Almost all variables are integers. There are over 800 similar blocks overall. Minimum 300,000 cycles of calculation. Average time is about 45 seconds. For reasons I don’t need to explain here, I should make it 2x faster. Code could be in different form if the people writing the algorithms were programmers. But they aren’t. They can handle up to some basic stuff like conditional blocks. This is something that can’t be changed.
I noticed some people coming here with intend to express irony. Please stay away. I need not your help. People who are willing to offer a constructive opinion are more than welcome to do so. In fact I thank them in advance for just making the effort to read such a long post. I am sorry for the bad code formatting, It was a failed effort to post it as code here.
if ( ZEChT01Pc[0] < ZEChT02Pc[0])
and( ZEChP01Pc[0] < ZEChP02Pc[0])
and( ZEChT01Bn[0] > ZEChP01Bn[0])
and( BncUp_TL_P_1_2[0] > ZEChT01Bn[0])
and( higSncZEChT01[0] < HZigCh30[0])
and( ((ZEChT01Pc[0] < LZigCh30[0]) )
or
( (ZEChT01Pc[0] < LZigCh3002[0] ) and( LZigCh30[0] < LZigCh3002[0] ) and( ZEChT01Pc[0] <= Bnc_Up_HZigCh_Pr[0]) )
or
( (ZEChT01Pc[0] < LZigCh3002[0] ) and( LZigCh30[0] < LZigCh3002[0] ) and( ZEChT01Pc[0] > Bnc_Up_HZigCh_Pr[0] ) and( ZEChP02Pc[0] < TFZ11EndPc[0])) )
and( ((TL_Pks_1_2.tl_getvalue(0) < LZigCh30[0] + ((HZigCh30[0] - LZigCh30[0] )*0.80)) )
or
( (ZEChT01Pc[0] < ULX2dly[0] ) and( C[0] > DLX2dly[0])) )
and (( (ZECoP01Bn[0] > ZEChP01Bn[0]) and (ZECoP01Bn[0] < ZEChT01Bn[0])
and (( (ZECoP01Pc[0] <= ZECoP02Pc[0]) and (C[0] > TL_ECo_Trs_1_2.tl_getvalue(0) )) or ( (ZECoP01Pc[0] > ZECoP02Pc[0]) )) )
or
( (ZECoP01Bn[0] = ZEChP01Bn[0]) and (ZECoP02Bn[0] < ZEChT02Bn[0]) ))
and (( (C[0] > ULX30[0]) and (C[1] <= ULX30[0]) and (ULX30[0] > TL_Pks_1_2.tl_getValue(0))
and (( (BrUpULX30[1] < ZEchT01Bn[0]) ) or ( (chgZigLCh[0] > BrUpULX30[1]) )) )
or
( (C[0] > TL_Pks_1_2.tl_getvalue(0)) and (C[1] <= TL_Pks_1_2.tl_getvalue(0)) and ( TL_Pks_1_2.tl_getValue(0) > ULX30[0]) and (BncUp_TL_P_1_2[1] < ZEchT01Bn[0]) ))
and( ((uniBrUpULX3002_bn[0] > ZEChT01Bn[0] ) and( uniBrUpULX30[0] > TL_Pks_1_2.tl_getvalue(0) ) and( uniBrUpULX3002[0] < TL_Pks_1_2.tl_getvalue(0)) )= false)
and( ((uniBrUpULX3002_bn[0] > ZEChT01Bn[0] ) and( uniBrUpULX30[0] > TL_Pks_1_2.tl_getvalue(0) ) and( uniBrUpULX3002[0] > TL_Pks_1_2.tl_getvalue(0)) )= false)
and( NoLong[0] = 0)
and( ((TL_Pks_1_2.tl_getvalue(0) < LZigCh30[0] ) and( chgZigLCh[0] < ZEChT01Bn[0] ) and( ULX30[0] > LZigCh30[0]) )= false)
and( ((((C[0] < DLXdly[0] ) and( HZigCh30[0] < DLXdly[0] - Tk(0.0050)) = false)))
or
( (ZEChT01Bn[0] = TFZ10EndBnum[0] ) and( ZEChT01Pc[0] < TFZ20EndPc[0] ) and( higSncZEChT01[0] > TFZ40EndPc[0])) )
and( ((ZEChP01Pc[0] > DLXdly[0] ) and( ZEChT01Pc[0] < DLXdly[0] ) and( HZigCh30[0] < DLXdly[0] )) = false)
and( ((higSncZEChT01[0] > HZigCh30[0] -Tk(0.0010) ) and( Bnc_Dn_HZigCh[0] > higbarSncZEChT01[0]) )= false)
and( ((TFZ10EndBnum[0] > TFZ11EndBnum[0] ) and( TFZ10Type[0]= 5 ) and( TFZ10Extension[0] = 0 ) and( ULX30[0] < LZigCh30[0]) )= false)
and( ((Bnc_Dn_LZigCh[0] > ZEChT01Bn[0] ) and( C[0] < LZigCh30[0]) )= false)
and( ((ZEChP01Pc[0] > DLXdly[0] ) and( ZEChT01Pc[0] < DLXdly[0] ) and( C[0] < DLXdly[0] ) and( First[0] = -1) )= false)
and( ((LZigCh3002[0] > DLXdly[0] ) and( LZigCh30[0] < DLXdly[0] ) and( C[0] < DLXdly[0]) and( HZigCh3002[0] > DLXdly[0] ) and( HZigCh30[0] < DLXdly[0] )) = false)
and( ((LZigCh3003[0] > DLXdly[0] ) and( LZigCh3002[0] < DLXdly[0] ) and( C[0] < DLXdly[0])
and( HZigCh3002[0] > DLXdly[0] ) and( HZigCh30[0] < DLXdly[0] ) and( LZigCh30[0] < DLXdly[0] ) and( currentbar - chgZigLCh[0] <= 3 )) = false)
and( ((((TFZ10EndBnum[0] > TFZ11EndBnum[0] ) and( C[0] > higSncShFrm[0] - ((higSncShFrm[0] - TFZ10EndPc[0])*0.5) ) and( higBarSncShFrm[0] <= ZEChP02Bn[0]) = false)))
or
( (ZEChT01Pc[0] < DLXdly[0] ) and( C[0] > DLXdly[0])) )
and( ((C[0] <= LZigCh30[0] ) and( H[0] > LZigCh30[0]) = false))
and( ((ZEChT01Pc[0] < ULXdly[0] ) and( ZEChT02Pc[0] < ULXdly[0] ) and( ZEChP01Pc[0] > ULXdly[0] )
and( ZEChP02Pc[0] > ULXdly[0] ) and( ZEChT01Pc[0] < ZEChT02Pc[0]) and (BncUpDLXdly[0] < ZEchT01Bn[0]) )= false)
and( ((((TFZ11EndBnum[0] > TFZ10EndBnum[0] ) and( ZEChT01Pc[0] > TFZ11EndPc[0] - ((TFZ11EndPc[0] - TFZ10EndPc[0])*0.382)) = false)))
or
( (C[0] > ULXdly[0])) )
and( ((((TFZ10EndBnum[0] > TFZ11EndBnum[0] ) and( TFZ20EndBnum[0] < TFZ11EndBnum[0] ) and( ZEChT01Pc[0] > TFZ11EndPc[0] - ((TFZ11EndPc[0] - TFZ20EndPc[0])*0.382)) )= false))
or
( (C[0] > ULXdly[0])) )
and( ((((TFZ20EndBnum[0] > TFZ11EndBnum[0] ) and( TFZ30EndBnum[0] < TFZ11EndBnum[0] ) and( ZEChT01Pc[0] > TFZ11EndPc[0] - ((TFZ11EndPc[0] - TFZ30EndPc[0])*0.382)) )= false))
or
( (C[0] > ULXdly[0])))
and( ((((TFZ30EndBnum[0] > TFZ11EndBnum[0] ) and( TFZ40EndBnum[0] < TFZ11EndBnum[0] ) and( ZEChT01Pc[0] > TFZ11EndPc[0] - ((TFZ11EndPc[0] - TFZ40EndPc[0])*0.382)) )= false))
or
( (C[0] > ULXdly[0])))
and( ((ZEChP01Pc[0] > ZEChP03Pc[0] ) and( ZEChP01Pc[0] > ZEChP04Pc[0] ) and( C[0] < DLXdly[0]) = false) )
and (( (( (LZigCh30[0] < DLXdly[0] ) and( LZigCh3002[0] > DLXdly[0] ) and( ZEChP01Pc[0] < DLXdly[0] ) and( C[0] < DLXdly[0]) ) = false))
or
( (ZEchT01Pc[0] = TFZ10EndPc[0]) or (ZEchT02Pc[0] = TFZ20EndPc[0]) or (ZEchT03Pc[0] = TFZ30EndPc[0]) ))
and( NoLong2[0] = 0 )
and( ((ZEChP02Pc[0] > ULX2dly[0] ) and( ZEChP01Pc[0] < ULXdly[0] ) and( C[0] < ULX2dly[0] ) and( BrDnDLXdly[0] < BrUpULXdly[0])
and( Min(ZEChT01Pc[0],ZEChT02Pc[0]) > ULXdly[0] - ((ULXdly[0] - DLXdly[0]) * 0.618)) )= false)
and( ((BrDnDLXdly[0] < BrUpULXdly[0] ) and( Min(ZEChT01Pc[0],ZEChT02Pc[0]) > ULXdly[0] - ((ULXdly[0] - DLXdly[0]) * 0.4))
and( TFZ10EndBnum[0] > TFZ11EndBnum[0] ) and( C[0] < ULX2dly[0] ) and( ULXdly[0] > ULX2dly[0] ) )= false)
and( ((BrDnDLXdly[0] < BrUpULXdly[0] ) and( TFZ10EndPc[0] > ULXdly[0] - ((ULXdly[0] - DLXdly[0]) * 0.4))
and( TFZ10EndBnum[0] < TFZ11EndBnum[0] ) and( C[0] < ULX2dly[0] ) and( ULXdly[0] > ULX2dly[0] ) )= false)
and( ((ZEChP02Pc[0] > ULX2dly[0] ) and( ZEChP01Pc[0] < ULXdly[0] ) and( C[0] < ULX2dly[0] ) and( BrDnDLXdly[0] < BrUpULXdly[0])
and( C[0] > LZigCh30[0] + ((HZigCh30[0] - LZigCh30[0]) * 0.768) ) and( C[0] < ULX2dly[0]) )= false)
and( ((LZigCh30[0] < DLXdly[0] ) and( DLXdly[0] < HZigCh30[0] ) and( C[0] > LZigCh30[0] + ((DLXdly[0] - LZigCh30[0])*0.618))
and( DLXdly[0] - C[0] < Tk(0.0040) ) and( C[0] < DLXdly[0] ) )= false)
and( ((((ZEChT01Bn[0] <> TFZ10EndBnum[0] ) and( ZEChT01Pc[0] >= LZigCh30[0])) = false))
or
( (ZEChT01Pc[0] < LZigCh30[0] ) and( C[0] > LZigCh30[0] ) and( LZigCh30[0] > ULXdly[0]))
or
( (LZigCh30[0] < LZigCh3002[0] ) and( chgZigLCh[0] > ZEChT01Bn[0] ) and( ZEChP01Pc[0] < LZigCh3002[0] ) and( C[0] > ZEChT02Pc[0] ) )
or
( (ZEChT01Pc[0] <= DLXdly[0] ) and( C[0] > DLXdly[0])))
and( ((C[0] < TFZ20EndPc[0] ) and( C[0] < LZigCh3002[0] ) and( TFZ20Type[0] > 3 ) and( ((TFZ20EndBnum[0] = ZEChT02Bn[0]) )or( (TFZ20EndBnum[0] = ZEChT03Bn[0]))) )= false)
and( ((((ZEChT01Bn[0] <> TFZ10EndBnum[0] ) and( ZEChT01Pc[0] < LZigCh30[0] ) and( LZigCh30[0] > ULXdly[0]) )= false))
or
( (C[0] < LZigCh30[0] + ((HZigCh30[0] - LZigCh30[0] )*0.618) ) and( HZigCh30[0] - C[0] >= Tk(0.0040)) ))
and( ((LZigCh30[0] < DLXdly[0] ) and( LZigCh3002[0] > DLXdly[0] ) and( ZEChP02Pc[0] < DLXdly[0] + Tk(0.0050) )
and( ZEChP02Pc[0] < LZigCh3002[0] ) and( C[0] < LZigCh3002[0] ) = false))
and ( (( (HZigCh30[0] < DLXdly[0]) and (HZigCh3002[0] > DLXdly[0]) and (ZEchT01Bn[0] = TFZ10EndBnum[0])
and (TFZ10Type[0] = 5 ) and (TFZ10Extension[0] = 0) and (DLXdly[0] < DLX2dly[0]) ) = false) )
and (( (( (chgULXdly[0] > ZEchP01Bn[0]) and (ULXdly[0] > ULX2dly[0]) and (C[0] < ULXdly[0]) and (ZEchT01Pc[0] > ULX2dly[0]) )=false))
or
( (TFZ10EndBnum[0] = ZEchT01Bn[0]) and (TFZ10Type[0] > 3) ))
and (( (( (chgULXdly[0] > ZEchP01Bn[0]) and (ULXdly[0] > ULX2dly[0]) and (C[0] < ULXdly[0]) and (C[0] < ULX2dly[0]))= false))
or
( ( ZechT01Pc[0] < ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.75)) and (C[0] > LZigCh30[0]) and (DLX30[0] > LZigCh30[0]) ))
and (( (( (chgULXdly[0] > ZEchP01Bn[0]) and (ULXdly[0] < ULX2dly[0]) and (C[0] < ULXdly[0]) ) = false))
or
( ( ZechT01Pc[0] < ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.75)) and (C[0] > LZigCh30[0]) and (DLX30[0] > LZigCh30[0]) ))
and (( (TFZ11EndBnum[0] = ZEchP02Bn[0]) and (TFZ11Type[0] > 3) and (min(ZEchT01Pc[0],ZechT02Pc[0]) = TFZ10EndPc[0]) and (C[0] < ULXdly[0])
and (TFZ10Type[0] = 3) and (TFZ10Extension[0] = 2) and (TFZ10EndPc[0] > ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.5)) ) = false)
and (( (TFZ11EndBnum[0] = ZEchP02Bn[0]) and (TFZ11Type[0] > 3) and (min(ZEchT01Pc[0],ZechT02Pc[0]) = TFZ10EndPc[0]) and (C[0] < ULXdly[0])
and (( (TFZ10Type[0] = 3) and (TFZ10Extension[0] = 2) )= false) and (TFZ10EndPc[0] > ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.8)) ) = false)
and (( (( (TFZ11EndBnum[0] = ZEchP02Bn[0]) and (TFZ11Type[0] > 3) and (min(ZEchT01Pc[0],ZechT02Pc[0]) <> TFZ10EndPc[0])) = false))
or
( (min(ZEchT01Pc[0],ZechT02Pc[0]) < ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.8)) )
or
( (Bnc_Up_LZigCh[0] > ZEchT01Bn[0]) and (ZEchT01Pc[0] > ZechP03Pc[0]) ))
and (( (ZechT01Pc[0] < ZechT02Pc[0]) and (ZechP01Pc[0] < ZechP02Pc[0]) and (ZEchT01Pc[0] > ULXdly[0]) and (C[0] < ZEchT02Pc[0]) and (C[0] > ULXdly[0]) ) = false)
and (( (ZechT01Pc[0] < ZechT02Pc[0]) and (ZechP01Pc[0] < ZechP02Pc[0]) and (ZEchT01Pc[0] > ULXdly[0]) and (ZEchP02Bn[0] = TFZ11EndBnum[0])
and (ZEchT02Bn[0]= TFZ20EndBnum[0]) and (ZEchT01Bn[0]= TFZ10EndBnum[0]) and (TFZ10Type[0] = 3) and (C[0] > ULXdly[0]) )= false)
and (( (ZechT01Pc[0] < ZechT02Pc[0]) and (ZechP01Pc[0] < ZechP02Pc[0]) and (ZEchT01Pc[0] > ULXdly[0]) and (ZEchP03Bn[0] = TFZ11EndBnum[0])
and (ZEchT02Bn[0]= TFZ20EndBnum[0]) and (ZEchT01Bn[0]= TFZ10EndBnum[0]) and (TFZ10Type[0] = 3) and (C[0] > ULXdly[0]) )= false)
and (((( (TFZ10Type[0] = 7) and (TFZ20type[0] = 5) and (TFZ10Extension[0] = 0) and (TFZ20Extension[0] = 0) and (TFZ10EndPc[0] > ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.5))) = false))
or
( (C[0] > ULXdly[0]) ) or ( (ZechT01Pc[0] < ULX2dly[0] ) and (C[0] > ULX2dly[0]) and (ULX2dly[0] < ULXdly[0]) ))
and (( (max(HZigCh30[0],HZigCh3002[0]) - LZigCh30[0] < Tk(0.0100)) and (C[0] > LZigCh30[0] + ((max(HZigCh30[0],HZigCh3002[0]) - LZigCh30[0])*0.618)) ) = false)
and (( (ZEchP02Pc[0] > ULXdly[0] - ((ULXdly[0] - DLXdly[0])*0.236)) and (ZEchT01Bn[0] <> TFZ10EndBnum[0]) and (BncUpDLXdly[0] < ZEchT01Bn[0])) = false)
and (( (Bnc_Dn_LZigCh[0] > ZEChT01Bn[0] ) and (C[0] < LZigCh30[0]) ) = false)
and (( (TFZ41EndBnum[0] > TFZ10EndBnum[0]) and (C[0] < ULXdly[0]) and (BncUpDLXdly[0] < ZEchT01Bn[0]) ) = false)
and ( GenL01[0] = false)
and ( GenL02[0] = false)
and ( GenL03[0] = false)
and ( GenL04[0] = True)
then
Thank you for reading.
I would definitely store the results in array as you pointed. Compiler don’t know the values you are computing and doesn’t store the results in some temporary stack in case of repetitive formulas. That’s what are variables for.
So yes, this will speed up your calculation time.
Update
Here is the simple example and dissasembly generated by Delphi 2009. As you can see in dissasembly storing results to the variables takes some CPU cycles though but comparing of booleans from the array takes only 4 instructions. So if you save your results once then your comparisions will take only these 4 instructions instead of 14 each time.
You can see the dissasembly by entering the breakpoint at debug mode and showing the Dissasembly window from View/Debug Windows/CPU Windows/Dissasembly.
Please note that this may differ a bit depending on your Delphi version.
And the dissasembly
At Button1Click you can see the direct comparision
At Button2Click storing of the results takes some time but comaprision itself takes only 4 instructions