1. Do I need to refactor this code?
- Posted by TheresNoTime Jul 02, 2013
- 1571 views
I have an auto-generated flat source code, thousands of monotone lines, many of which have more than a dozen comparisons. Comparisons are often repeated. Sometimes, all except one:
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if
Obviously, this code can be optimized:
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) then if (x = 9) return 1 end if if (y = 10) return 2 end if if (z = 11) return 3 end if end if
Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.
2. Re: Do I need to refactor this code?
- Posted by DerekParnell (admin) Jul 02, 2013
- 1472 views
I have an auto-generated flat source code, thousands of monotone lines, many of which have more than a dozen comparisons. Comparisons are often repeated. Sometimes, all except one:
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if
Obviously, this code can be optimized:
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) then if (x = 9) return 1 end if if (y = 10) return 2 end if if (z = 11) return 3 end if end if
Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.
Generated Euphoria code is not this sophisticated yet.
You might want to try this approach, depending on how you automate the code generation ...
sequence temp temp = {a,b,c,d,e,f,g,h,i,x} switch temp do case {0,1,2,3,4,5,6,7,8,9} then return 1 end case case {0,1,2,3,4,5,6,7,8,10} then return 2 end case case {0,1,2,3,4,5,6,7,8,11} then return 3 end case end switch
3. Re: Do I need to refactor this code?
- Posted by Spock Jul 02, 2013
- 1502 views
I have an auto-generated flat source code, thousands of monotone lines..
How serious are you about optimising these operations? If you could give a bit more detail about the ranges of comparison values and what they get compared to it must be possible to reduce the problem to a lookup using, eg, find()
Spock
4. Re: Do I need to refactor this code?
- Posted by TheresNoTime Jul 03, 2013
- 1435 views
You might want to try this approach, depending on how you automate the code generation ...
Nice idea, but it is impossible. Comparison operation can be varied, not only check for equality. I regret that misled. I would like to draw attention to the structure of the code.
5. Re: Do I need to refactor this code?
- Posted by TheresNoTime Jul 03, 2013
- 1420 views
I have an auto-generated flat source code, thousands of monotone lines..
How serious are you about optimising these operations?
In fact, not very serious. I suspect that thousands of comparisons to slow down today's computers a few thousandths (maybe a few hundredths) of a second.
If you could give a bit more detail about the ranges of comparison values and what they get compared to it must be possible to reduce the problem to a lookup using, eg, find()
I think, main detail is order of operations. If the next line have same operations, they start from the beginning of the line and are in the same order.
if (a = 0 or b > 10) and (c < 10 or d = 100) then return 1 end if if (a = 0 or b > 10) and (c < 10 or d = 100) and e[f] then return 2 end if if (a = 0 or b > 10) and (c < 10 or d = 100) and e[g] then return 3 end if if (a = 0 or b > 10) and (c < 10 or d = 100) and e[g] and (h != 115) then return 4 end if
So, it is easy to create recursive algorithm for optimizing: all "and"s must be converted to "sub-if"s. Each line is compared with previous lines. Then we search maximal number of similar expressions between "and"s. Found expressions are removed, and the line is inserted into the appropriate "sub-if".
if (a = 0 or b > 10) then if (c < 10 or d = 100) then if e[f] then return 2 end if if e[g] then if (h != 115) then return 4 end if return 3 end if return 1 end if end if
6. Re: Do I need to refactor this code?
- Posted by useless_ Jul 03, 2013
- 1384 views
<snip>
You might want to try this approach, depending on how you automate the code generation ...
sequence temp temp = {a,b,c,d,e,f,g,h,i,x} switch temp do case {0,1,2,3,4,5,6,7,8,9} then return 1 end case case {0,1,2,3,4,5,6,7,8,10} then return 2 end case case {0,1,2,3,4,5,6,7,8,11} then return 3 end case end switch
Pretty in many ways. Is there a "don't care" value, or a helpful hint to catch a error or fall-thru in the Eu source code, such that
sequence temp temp = {0,1,2,3,4,5,6,7,"<12",9} switch temp do -- "" = type sequence flag = "don't care" (yeas, aka an error) case {0,1,2,3,4,5,6,7,"",9} then return {1,temp} end case end switch
So while Eu didn't process the "<12", temp is otherwise tested and returned to the user in a sequence for extra processing?
Or praps this:
type P_1(integer x) return x >= 0 and x <= 23 end type sequence temp temp = {atom,atom,atom,atom,atom,atom,atom,atom,P_1,atom} switch temp do case {0,1,2,3,4,5,6,7,12,9} then return 1 end case end switch
Or praps there is some way to push a list of types into the case comparisons internally on a case-by-case basis?
I have also had a situation where this would have been extremely valuable in optical pattern recognition or extracting details about motion. It would also be handy in resolving tags in content addressable data, or misspelling, or ?
useless
7. Re: Do I need to refactor this code?
- Posted by mattlewis (admin) Jul 03, 2013
- 1392 views
Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.
If you have information that this is a real bottleneck, then it may make practical sense. While euphoria won't completely optimize out duplicate comparisons, it does do short circuiting, so if, in a long string of and operations, it find something false, it won't perform the rest of the operations. Likewise, if a true value is found in the first argument of an or operation, it won't bother with the second.
Most of your code doesn't need to be optimized, as a general rule. And due to short circuiting, it might be easier or more effective to reorder comparisons if you have some knowledge of the underlying data.
Matt
8. Re: Do I need to refactor this code?
- Posted by TheresNoTime Jul 03, 2013
- 1389 views
Thanks for ideas! Your answers led me to this thought. We read all the lines and find the most frequent combination of two conjunctions (x and y and z). Replace it with a temporary Boolean variable. Declare it before the first combination (x and y and z). Repeat until such combinations will not stay!
Original code:
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if
After 1st iteration:
integer tmp1 = (a = 0) and (b = 1) and (c = 2) if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if
After 2nd iteration:
integer tmp1 = (a = 0) and (b = 1) and (c = 2) integer tmp2 = tmp1 and (d = 3) and (e = 4) if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if
After 3rd iteration:
integer tmp1 = (a = 0) and (b = 1) and (c = 2) integer tmp2 = tmp1 and (d = 3) and (e = 4) integer tmp3 = tmp2 and (f = 5) and (g = 6) if tmp3 and (h = 7) and (i = 8) and (x = 9) return 1 end if if tmp3 and (h = 7) and (i = 8) and (y = 10) return 2 end if if tmp3 and (h = 7) and (i = 8) and (z = 11) return 3 end if
After 4th iteration:
integer tmp1 = (a = 0) and (b = 1) and (c = 2) integer tmp2 = tmp1 and (d = 3) and (e = 4) integer tmp3 = tmp2 and (f = 5) and (g = 6) integer tmp4 = tmp3 and (h = 7) and (i = 8) if tmp4 and (x = 9) return 1 end if if tmp4 and (y = 10) return 2 end if if tmp4 and (z = 11) return 3 end if
That's all! The method is not ideal, but it is universal, infallible and simple to implement.