WildByDesign Posted Monday at 03:44 PM Posted Monday at 03:44 PM I was reading some docs recently for If...Then and noticed one of the paragraphs: Quote This version of the If statement is used to execute a single statement without the overhead of an EndIf. I've added bold to the part that I have a concern about. According to the docs, that tells me that a single line If statement performs better in comparison to and If statement that ends with EndIf. That made me start to think about converting all of my If...EndIf statements to single line If statements. However, since I have been performance testing everything that goes into my current project, I realized pretty quickly that the docs were wrong about the EndIf "overhead". So I decided to search the forums here since these forums are a gold mine of information. I came across a great post (with script) by the great @guinness for comparing the performance. I have updated the script a bit: Global $iTimer, $iVariable = 1 $iTimer1 = TimerInit() For $A = 1 To 10000 If $iVariable Then $iVariable = 1 Next $iTimer1 = Round(TimerDiff($iTimer1), 1) ConsoleWrite("10,000 runs (single line If statement): " & @TAB & $iTimer1 & "ms" & @CRLF) $iTimer2 = TimerInit() For $A = 1 To 10000 If $iVariable Then $iVariable = 1 EndIf Next $iTimer2 = Round(TimerDiff($iTimer2), 1) ConsoleWrite("10,000 runs (If statement with EndIf): " & @TAB & @TAB & $iTimer2 & "ms" & @CRLF & @CRLF) $iDifference = Round(($iTimer1 - $iTimer2) / $iTimer2, 2) ConsoleWrite("Percentage Difference: " & @TAB & @TAB & @TAB & @TAB & @TAB & @TAB & $iDifference * 100 & "%" & @CRLF) The difference is really quite interesting. But as I mentioned, the problem that I have is with the wording "without the overhead of an EndIf" in the documentation. If it wasn't for me doing performance testing comparisons recently, I probably would have went ahead and changed dozens of If...EndIf statements in my current project to single line If statements and these get called sometimes dozens of times per second. As always, thank you for your time.
argumentum Posted Monday at 04:39 PM Posted Monday at 04:39 PM Global $iTimer, $iVariable = 1 For $tryNo = 1 To 3 Sleep(1000) $iTimer1 = TimerInit() For $A = 1 To 10000 If $iVariable Then $iVariable = 1 Next $iTimer1 = Round(TimerDiff($iTimer1), 1) ConsoleWrite("10,000 runs (single line If statement): " & @TAB & $iTimer1 & "ms" & @CRLF) $iTimer2 = TimerInit() For $A = 1 To 10000 If $iVariable Then $iVariable = 1 EndIf Next $iTimer2 = Round(TimerDiff($iTimer2), 1) ConsoleWrite("10,000 runs (If statement with EndIf): " & @TAB & @TAB & $iTimer2 & "ms" & @CRLF) $iDifference = Round(($iTimer1 - $iTimer2) / $iTimer2, 2) ConsoleWrite("Percentage Difference: " & @TAB & @TAB & @TAB & @TAB & @TAB & @TAB & $iDifference * 100 & "%" & @CRLF & @CRLF) Next Exit 10,000 runs (single line If statement): 40.5ms 10,000 runs (If statement with EndIf): 3.1ms Percentage Difference: 1206% 10,000 runs (single line If statement): 5.7ms 10,000 runs (If statement with EndIf): 3ms Percentage Difference: 90% 10,000 runs (single line If statement): 5.8ms 10,000 runs (If statement with EndIf): 3ms Percentage Difference: 93% I'll write what makes the code more readable. Anyone having to depend on this, needs to rethink their code. My 2 cents mlibre2, SOLVE-SMART and WildByDesign 2 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
SOLVE-SMART Posted Monday at 06:11 PM Posted Monday at 06:11 PM I am also opinionated about single line statements. They decrease the readability often more than just a bit. My recommendation for your specific case: Try to optimise the algorithms, function logic instead of if-condition optimisation. I strongly believe there is more potential to optimize 😀 . Best regards Sven WildByDesign 1 ==> AutoIt related: 🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet Spoiler 🌍 Au3Forums 🎲 AutoIt (en) Cheat Sheet 📊 AutoIt limits/defaults 💎 Code Katas: [...] (comming soon) 🎭 Collection of GitHub users with AutoIt projects 🐞 False-Positives 🔮 Me on GitHub 💬 Opinion about new forum sub category 📑 UDF wiki list ✂ VSCode-AutoItSnippets 📑 WebDriver FAQs 👨🏫 WebDriver Tutorial (coming soon)
WildByDesign Posted Monday at 07:56 PM Author Posted Monday at 07:56 PM 1 hour ago, SOLVE-SMART said: Try to optimise the algorithms, function logic instead of if-condition optimisation. I strongly believe there is more potential to optimize Thanks Sven. I agree with you 100%. Every time I look it over, I always find things that can be optimized or improved in various ways. I seem to actually enjoy this aspect of learning better ways to do things. Normally I don’t worry too much about performance. But in this case it’s for a WinEventHook so it has to be able to handle everything that goes through the hook. SOLVE-SMART 1
WildByDesign Posted Monday at 07:58 PM Author Posted Monday at 07:58 PM 3 hours ago, argumentum said: I'll write what makes the code more readable. I agree, for sure. Readable code is by far the most important choice.
rcmaehl Posted yesterday at 12:16 AM Posted yesterday at 12:16 AM 5 hours ago, SOLVE-SMART said: Try to optimise the algorithms, function logic instead of if-condition optimisation. I strongly believe there is more potential to optimize 😀 . Big Agree I mean, it definitely helps if you're fighting a race condition but it's not a good idea to get yourself in one in the first place. 👀 WildByDesign 1 My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated. My Projects WhyNotWin11, MSEdgeRedirect Cisco Finesse, Github, IRC UDF, WindowEx UDF
Solution Popular Post AspirinJunkie Posted yesterday at 04:45 AM Solution Popular Post Posted yesterday at 04:45 AM To break down the performance behavior in more detail: It depends on whether the condition is met or not. The following test script: expandcollapse popupGlobal Const $N = 1e7 Global $iT, $f_Overhead ConsoleWrite(@CRLF & " name time" & @CRLF & "--------------------------------------" & @CRLF) ; determine the overhead of loop [and optional other stuff] $iT = TimerInit() For $i = 1 To $N Next $f_Overhead = TimerDiff($iT) $iVariable = 1 $iT = TimerInit() For $i = 1 To $N If $iVariable Then $iVariable = 1 EndIf Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\n", "If-EndIf True", ($iT-$f_Overhead) / $N)) $iVariable = 0 $iT = TimerInit() For $i = 1 To $N If $iVariable Then $iVariable = 1 EndIf Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\n", "If-EndIf False", ($iT-$f_Overhead) / $N)) $iVariable = 1 $iT = TimerInit() For $i = 1 To $N If $iVariable Then $iVariable = 1 Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\n", "If-OneLiner True", ($iT-$f_Overhead) / $N)) $iVariable = 0 $iT = TimerInit() For $i = 1 To $N If $iVariable Then $iVariable = 1 Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\n", "If-OneLiner False", ($iT-$f_Overhead) / $N)) produces for me: name time -------------------------------------- If-EndIf True: 0.000260 ms If-EndIf False: 0.000161 ms If-OneLiner True: 0.000481 ms If-OneLiner False: 0.000088 ms So it depends on whether the condition is met or not. If it is met, then the classic If-EndIf is faster. If it is not met, the one-liner is faster. When conditions are balanced, their times will be roughly the same. If you can estimate whether the vast majority of conditions are true or false, then you could certainly optimize on that basis. The relative differences are quite significant. But in absolute terms, they are completely subordinated. To put the measured numbers into perspective: we are talking about a difference between 160 nanoseconds and 88 nanoseconds – not milliseconds, not even microseconds! No, nanoseconds! These are therefore overshadowed by any other parts of the code. (unless the script consists purely of millions of consecutive if queries). This decision therefore makes no relevant difference to the overall script. However, this makes the answer for this thread quite straightforward (as the others have already said): which of the two is used is independent of any performance considerations. The decision should be based solely on readability and clarity at the specific code location. mlibre2, WildByDesign, SOLVE-SMART and 2 others 3 2
WildByDesign Posted yesterday at 11:08 AM Author Posted yesterday at 11:08 AM 6 hours ago, AspirinJunkie said: So it depends on whether the condition is met or not. If it is met, then the classic If-EndIf is faster. If it is not met, the one-liner is faster. When conditions are balanced, their times will be roughly the same. Thank you so much. That was very enlightening, both the script and the way that you worded everything. I had not even put any thought into whether the performance would differ depending on whether or not the condition was met. And then, as you mentioned, these are really nanoseconds that were are talking about here and therefore likely not even worth my time trying to optimize in this area. As others have mentioned, I should ensure that the code in this area is readable first and foremost. 16 hours ago, SOLVE-SMART said: Try to optimise the algorithms, function logic instead of if-condition optimisation. You were right about not focusing on optimizing if-conditions and that I should be focusing optimization elsewhere. For what it's worth, despite AutoIt not being built for or intended for performance, I am really happy with the performance that I get out of my _WinEventProc function (SetWinEventHook). It's a busy function but AutoIt handles it well and I had already put a lot of optimization work into it over the past few months among other changes to make it as efficient as possible. Some of you might already be aware that I had already made significant performance improvements recently, thanks for the Fastest method to get process name from handle thread which got me making custom versions of all of the _WinAPI_* functions that I already use. There were some real, legitimate differences in performance that came out of that thread. Perhaps me nitpicking about If...Then statement performance is just being greedy and trying to pull in more performance in an area that is less relevant but also likely that I just need to focus my mind elsewhere and stop looking for performance improvements, when in reality, I am more than satisfied with the overall performance. 😄
rcmaehl Posted yesterday at 01:30 PM Posted yesterday at 01:30 PM (edited) 8 hours ago, AspirinJunkie said: produces for me: name time -------------------------------------- If-EndIf True: 0.000260 ms If-EndIf False: 0.000161 ms If-OneLiner True: 0.000481 ms If-OneLiner False: 0.000088 ms I decided to investigate by inverting the conditions via NOT (and inverting variable values and assignments) with the following results. If-OneLiner False becomes the slowest of the bunch. Edit: Fixed variables. Got similar results as previous. name time -------------------------------------- IfNot-EndIf True: 0.000334 ms IfNot-EndIf False: 0.000226 ms IfNot-OneLiner True: 0.000539 ms IfNot-OneLiner False: 0.000156 ms Edited yesterday at 01:40 PM by rcmaehl Fix Bad Code WildByDesign 1 My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated. My Projects WhyNotWin11, MSEdgeRedirect Cisco Finesse, Github, IRC UDF, WindowEx UDF
mlibre2 Posted yesterday at 01:32 PM Posted yesterday at 01:32 PM They made me doubt for a moment, I think this condition is one of the few admitted, generally it has to be enclosed in other languages {...} myLogin 🛡️
rcmaehl Posted 23 hours ago Posted 23 hours ago (edited) I'm sure there's some CPU Branch Predictor Optimizations that can be done. However, as you've seen in your Process Name from Handle thread, there's a LOT more performance that can be gained by reusing resources, cutting out unneeded code, and other optimizations. Also, don't be afraid to do things out of order. You may be surprised what still works $iSIHost = ProcessExists("sihost.exe") While True $aProcessList = _WinAPI_EnumChildProcess($iSIHost) If @error Then ContinueLoop ProcessClose($aProcessList[1][0]) $sCommandline = _WinAPI_GetProcessCommandLine($aProcessList[1][0]) $sProcessPath = _WinAPI_GetProcessFileName($aProcessList[1][0]) WEnd And you can always fix a mistake if you're overzealous $iSIHost = ProcessExists("sihost.exe") While True $aProcessList = _WinAPI_EnumChildProcess($iSIHost) If @error Then ContinueLoop ProcessClose($aProcessList[1][0]) $sCommandline = _WinAPI_GetProcessCommandLine($aProcessList[1][0]) $sProcessPath = _WinAPI_GetProcessFileName($aProcessList[1][0]) If Not $aProcessList[1][1] = "msedge.exe" Then ShellExecute($sProcessPath, $sCommandLine) WEnd Edited 23 hours ago by rcmaehl WildByDesign 1 My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated. My Projects WhyNotWin11, MSEdgeRedirect Cisco Finesse, Github, IRC UDF, WindowEx UDF
argumentum Posted 23 hours ago Posted 23 hours ago 2 hours ago, WildByDesign said: Perhaps me nitpicking about.... ..perhaps.. . Perhaps is good. Not because one of your questions did not bring the house down, or you were right or not about making a big deal out of, something. Is good, is all good. So keep asking if there is a question. I enjoy the threads even if I don't have either time, or anything to contribute to it. This if-then-else thing, ...I had no idea, nor ever came up in my brain. Thinking about it, at times I use Switch as an If when is practical ( I don't care much about speed or memory with today's hardware ) Andreik and WildByDesign 2 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
WildByDesign Posted 20 hours ago Author Posted 20 hours ago 3 hours ago, argumentum said: So keep asking if there is a question. I enjoy the threads even if I don't have either time, or anything to contribute to it. I appreciate it. Thank you. I figure that it never hurts to ask questions and sometimes asking questions and having dialogue with like-minded people. 3 hours ago, argumentum said: Thinking about it, at times I use Switch as an If when is practical That actually reminds me that I was planning to look into that at some point in time. I don't have very much experience with Switch so far. I should see if I can convert some of my script over to Switch because it's nice and tidy looking.
WildByDesign Posted 20 hours ago Author Posted 20 hours ago 3 hours ago, rcmaehl said: Also, don't be afraid to do things out of order. You may be surprised what still works Thank you. That is great information. I've only been learning AutoIt for a little over a year now but I really do need to start thinking outside the box a bit more and get a bit more creative. AutoIt definitely provides the flexibility for that creativity.
Andreik Posted 20 hours ago Posted 20 hours ago (edited) It's good to have a constant desire to write good and fast running code but on this matter I have the same feeling as @argumentum and as long as I use AutoIt I don't care too much so I use a mix of different conditional statements that make sense in each situation. If the performance it's such an issue to make me fight for each 1000th part of a ms probably I want to code in another language. But again as a good practice and for learning purpose your question is legit. Edited 20 hours ago by Andreik argumentum and WildByDesign 2
WildByDesign Posted 19 hours ago Author Posted 19 hours ago 52 minutes ago, Andreik said: If the performance it's such an issue to make me fight for each 1000th part of a ms probably I want to code in another language I agree, that does make the most sense. I think the problem here is that I became too obsessed/interested with gaining more performance savings when it really was not needed. But on the positive side, I have learned so much more from this performance adventure and did end up making things much more efficient with some aspects of it. And I absolutely must say, the AutoIt community here is the best. I love it how many people come together with different ideas from various perspectives.
Numeric1 Posted 16 hours ago Posted 16 hours ago Hi everyone, Thanks for this super interesting thread! I really appreciate the educational aspect of this topic and the way you've shared your insights. Your in-depth investigations into performance are inspiring, and it's impressive to see how much you've dug into the subject as a team! 😊 Just a small remark: while reading your discussions on optimization, I was surprised not to see any mention of the ternary operator. It seems to me that in some cases, it could be an elegant and concise alternative to simplify If...EndIf statements, while also offering a slight performance boost. Have you explored this approach collectively, or perhaps it wasn't applicable to this specific case? WildByDesign 1 From 0 and 1 to the stars, it all starts with binary, Numeric1
WildByDesign Posted 16 hours ago Author Posted 16 hours ago 28 minutes ago, Numeric1 said: Just a small remark: while reading your discussions on optimization, I was surprised not to see any mention of the ternary operator. It seems to me that in some cases, it could be an elegant and concise alternative to simplify If...EndIf statements, while also offering a slight performance boost. Have you explored this approach collectively, or perhaps it wasn't applicable to this specific case? Thank you for your response. I appreciate that you've taken time to share some insight and suggestions as well. I personally have never used Ternary before. I'm still quite new to AutoIt and have a lot to learn. So to be perfectly honest, I don't really have a good understanding of how or when to use Ternary over the other options. This thread (and possibly another thread or two) was really about trying to get the most performance out of, or better efficiency, of the _WinEventProc (SetWinEventHook) function of my Immersive UX project. Since all running processes on the system filter through it, finding various ways to make it more efficient has been incredibly helpful. With the help of this community, it has been really beneficial. If you are curious if Ternary can fit in anywhere and if you have a few minutes, you can have a peak at the hook function (https://github.com/WildByDesign/ImmersiveUX/blob/main/ImmersiveEngine.au3#L587). It's got a lot of things that help make it more efficient, but I am always open to more. And most importantly, I am always interested in learning more. Numeric1 1
rcmaehl Posted 15 hours ago Posted 15 hours ago (edited) 1 hour ago, WildByDesign said: Thank you for your response. I appreciate that you've taken time to share some insight and suggestions as well. I personally have never used Ternary before. I'm still quite new to AutoIt and have a lot to learn. So to be perfectly honest, I don't really have a good understanding of how or when to use Ternary over the other options. This thread (and possibly another thread or two) was really about trying to get the most performance out of, or better efficiency, of the _WinEventProc (SetWinEventHook) function of my Immersive UX project. Since all running processes on the system filter through it, finding various ways to make it more efficient has been incredibly helpful. With the help of this community, it has been really beneficial. If you are curious if Ternary can fit in anywhere and if you have a few minutes, you can have a peak at the hook function (https://github.com/WildByDesign/ImmersiveUX/blob/main/ImmersiveEngine.au3#L587). It's got a lot of things that help make it more efficient, but I am always open to more. And most importantly, I am always interested in learning more. Quote False Positives seem to be a "cat & mouse game" Try adding -mx=0 in your CI for 7z Edited 14 hours ago by rcmaehl fix flag My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated. My Projects WhyNotWin11, MSEdgeRedirect Cisco Finesse, Github, IRC UDF, WindowEx UDF
WildByDesign Posted 14 hours ago Author Posted 14 hours ago 17 minutes ago, rcmaehl said: Try adding -mx=0 in your CI for 7z That's a good suggestion. I will give it a try. Defender doesn't detect the actual compiled binaries, just the archive that contains the binaries. I hadn't thought about changing the compression like that but it definitely makes sense. Thanks.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now