![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks. |
| |||||||
![]() |
| |
| | #1 (permalink) |
| | FYI: 'continue' in 'for' loops is VERY slow Recently I have slightly refactored a script and noticed drastically improved performance. It turned out that 'continue' in 'for' loop is VERY slow, in my case it used to take much more time than what a loop body should actually do. Example: > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } } } TotalMilliseconds : 10.8296 > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } else { > continue } } } TotalMilliseconds : 170.6035 Can anybody repro\confirm this? -- Thanks, Roman Kuzmin |
My System Specs![]() |
| | #2 (permalink) |
| | Re: FYI: 'continue' in 'for' loops is VERY slow > Recently I have slightly refactored a script and noticed drastically > improved performance. It turned out that 'continue' in 'for' loop is VERY > slow, in my case it used to take much more time than what a loop body should > actually do. > > Example: > > > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } } } > > TotalMilliseconds : 10.8296 > > > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } else { > > continue } } } > > TotalMilliseconds : 170.6035 > > Can anybody repro\confirm this? > Yes, it's about 20x slower for me too. Is continue an expensive statement in other languages too such as C++? Can't say I've ever noticed it. Does Powershell compile script blocks down to IL? I guess you've maybe got anther script-block around the continue that needs to be entered into, unless it's optimized away? function time { [datetime]$startTime = [datetime]::now for($e=0; ; ++$e) { if ($e -ge 1000) { break } } [datetime]$endTime = [datetime]::now ($endTime - $startTime).TotalSeconds } function time2 { [datetime]$startTime = [datetime]::now for($e=0; ; ++$e) { if ($e -ge 1000) { break } else { continue } } [datetime]$endTime = [datetime]::now ($endTime - $startTime).TotalSeconds } 0.01 v 0.2 |
My System Specs![]() |
| | #3 (permalink) |
| | Re: FYI: 'continue' in 'for' loops is VERY slow If I had to guess, I'd say it's because continue, break and return are all implemented by throwing exceptions which are caught and handled by the Execute() method of whichever loop control mechanism (e.g., Parser+DoWhileStatementNode in System.Management.Automation.dll) is running the loop. You can see it by opening System.Management.Automation.dll (in your Framework\v2.0.50727 folder on XP) in Reflector (http://www.aisto.com/roeder/dotnet/) and taking a look at Parser+FlowControlNode.Execute(). Hope this helps. -- Ryan Milligan "Duncan Smith" <DSmith1974@googlemail.com> wrote in message news:1175712048.596748.86350@l77g2000hsb.googlegroups.com... > >> Recently I have slightly refactored a script and noticed drastically >> improved performance. It turned out that 'continue' in 'for' loop is VERY >> slow, in my case it used to take much more time than what a loop body >> should >> actually do. >> >> Example: >> >> > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } } } >> >> TotalMilliseconds : 10.8296 >> >> > time { for($e=0; ; ++$e) { if ($e -ge 1000) { break } else { >> > continue } } } >> >> TotalMilliseconds : 170.6035 >> >> Can anybody repro\confirm this? >> > > Yes, it's about 20x slower for me too. Is continue an expensive > statement in other languages too such as C++? Can't say I've ever > noticed it. Does Powershell compile script blocks down to IL? I > guess you've maybe got anther script-block around the continue that > needs to be entered into, unless it's optimized away? > > function time > { > [datetime]$startTime = [datetime]::now > > for($e=0; ; ++$e) > { > if ($e -ge 1000) > { > break > } > } > > [datetime]$endTime = [datetime]::now > ($endTime - $startTime).TotalSeconds > } > > function time2 > { > [datetime]$startTime = [datetime]::now > > for($e=0; ; ++$e) > { > if ($e -ge 1000) > { > break > } > else > { > continue > } > } > > [datetime]$endTime = [datetime]::now > ($endTime - $startTime).TotalSeconds > > } > > 0.01 v 0.2 > |
My System Specs![]() |
| | #4 (permalink) |
| | Re: FYI: 'continue' in 'for' loops is VERY slow If so, it looks quite dirty... and I hope this approach is temporary. -- Thanks, Roman Kuzmin |
My System Specs![]() |
| | #5 (permalink) |
| | Re: FYI: 'continue' in 'for' loops is VERY slow On Apr 4, 10:28 pm, "Ryan Milligan" <Cei...@hotmail.com> wrote: > If I had to guess, I'd say it's because continue, break and return are all > implemented by throwing exceptions which are caught and handled by the > Execute() method of whichever loop control mechanism (e.g., > Parser+DoWhileStatementNode in System.Management.Automation.dll) is running > the loop. You can see it by opening System.Management.Automation.dll (in > your Framework\v2.0.50727 folder on XP) in Reflector > (http://www.aisto.com/roeder/dotnet/) and taking a look at > Parser+FlowControlNode.Execute(). Hope this helps. > > -- Ryan Milligan > Certainly makes a good deal of sense, well found! This reflector tool looks extremely useful, this will get a lot of usage from me - kind of like having the MFC code to browse through. I see that you can search for 'continue' and it finds ContinueException in system.management.automation, but how did you then find a reference to that tucked away in the FlowControl.Execute method? I can't see a way to search all of the disassembled code? Do you think there's a way that you could debug into the code that reflector shows? Maybe by inserting a 'stop' command in a .ps1 file (or whatever the powershell equivalent of an _asm int 3; breakpoint call is) and then hooking it up to an instance of VS2005 for a debug session? Many thanks, Duncan |
My System Specs![]() |
| | #6 (permalink) |
| | Re: FYI: 'continue' in 'for' loops is VERY slow Check out the "Analyzer" feature -- right click on something in the left pane and select Analyzer (or select it and press ctrl-R), and a tree view will open up under the code view. Expand that, and you'll see nodes like "Depends Upon", "Used By", etc, depending on what kind of node you selected. If you selected ContinueException, you can expand the Used By node and see the list of methods that use the type. Select one and press space, and you'll see it in the code view. Pretty nifty, eh? As for debugging the code generated by Reflector, I've thought about this myself many times. Basically, you'd need to write an extension to Reflector that would generate a folder of source code, and a .pdb file from the .dll that maps offsets in the IL to lines in the generated source code. I haven't looked to see if the Reflector API provides access to all the information you would need, but I suspect that it might. Maybe I'll get around to looking into it some time. -- Ryan Milligan "Duncan Smith" <DSmith1974@googlemail.com> wrote in message news:1175849380.925327.283700@w1g2000hsg.googlegroups.com... > On Apr 4, 10:28 pm, "Ryan Milligan" <Cei...@hotmail.com> wrote: >> If I had to guess, I'd say it's because continue, break and return are >> all >> implemented by throwing exceptions which are caught and handled by the >> Execute() method of whichever loop control mechanism (e.g., >> Parser+DoWhileStatementNode in System.Management.Automation.dll) is >> running >> the loop. You can see it by opening System.Management.Automation.dll (in >> your Framework\v2.0.50727 folder on XP) in Reflector >> (http://www.aisto.com/roeder/dotnet/) and taking a look at >> Parser+FlowControlNode.Execute(). Hope this helps. >> >> -- Ryan Milligan >> > > Certainly makes a good deal of sense, well found! > > This reflector tool looks extremely useful, this will get a lot of > usage from me - kind of like having the MFC code to browse through. > > I see that you can search for 'continue' and it finds > ContinueException in system.management.automation, but how did you > then find a reference to that tucked away in the FlowControl.Execute > method? I can't see a way to search all of the disassembled code? > > Do you think there's a way that you could debug into the code that > reflector shows? Maybe by inserting a 'stop' command in a .ps1 file > (or whatever the powershell equivalent of an _asm int 3; breakpoint > call is) and then hooking it up to an instance of VS2005 for a debug > session? > > Many thanks, > > Duncan > |
My System Specs![]() |
![]() |
| Thread Tools | |
| |
Similar Threads | ||||
| Thread | Forum | |||
| Is there a 'continue' construct for loops in VBScript | VB Script | |||
| Loops inside Cmdlets | PowerShell | |||
| Task manager loops back? | Vista General | |||
| Traps and Foreach loops | PowerShell | |||
| Next fucntion in loops? | PowerShell | |||