On 06/05/2018 20:12, Richard Gaskin via use-livecode wrote:

Ah, that makes sense.  It's not so much the recursion per se, but the more general advantage of inline processing vs handler calls.

Exactly.
In the test case below you know how many levels deep you're going, which seems a good fit for inline loops. But how do we handle cases like directory traversal, where we don't know in advance how deep we'll need to go?

In this test case I do know how many levels - but the code makes no use of that knowledge, it simply exits when we get down to 0. For an example of how to handle directory recursion, see Ben's earlier post in this thread. Or I've included my current version below - I return a 2-level array of folder / file / data ... rather than a file-per-line.
It's at least comforting to see that while the overhead of handler calls is significant, it's mostly in relative comparison: If I read that correctly, there are 1000 iterations of 100 operations, for a total of 100k operations.  If my coffee is working, that means an overhead of just 0.00208 ms per operation when called in a separate handler, no? (thinking 273ms total for separate handler - 65ms for inline, per 100k operations).

Yep - though it gets higher with more parameters. My recursive 'walker' needed 4 parameters, so the overhead was higher. Note that if I was writing a recursive tree-walker now, I'd make it a private function, so I could keep the parameter checks only at the top (i.e. public) level, and recurse without repeating them. I might even move most of the parameters into script-local variables, since I know the code is interrupt-safe.
With directory traversal, I'd guess the overhead of physically touching each inode would outweigh that manyfold.

Yeah - though it's particularly hard to test adequately. When I was trying to benchmark it, I found that to get consistent results, I had to run the test 2 or 3 times and ignore the first, highly variable, run. Which basically means that I was seeing results with the disk-cache fully engaged, and therefore likely to underestimate the importance of the disk operations in any real context.
Still useful to keep in mind: when inline code can do the job clearly, it will be more efficient.
Below is my current non-recursive walker.
NB - it goes to some trouble to allow you to pass in a relative path name, and maintain that in the result. That is the opposite of what is commonly done (i.e. using absolute path/file names); I did this to make it easier to compare multiple trees. If you want the traditional result, simply do
   put the defaultfolder into temp -- gives the absolute path
   getArrayOfFiles temp, tMyArray
but if you want "my" twist, you'd do
   getArrayOfFiles ".", tMyArray

-- Alex.
# Produce an array of folders + files with the "full" relative paths
command getArrayOfFiles pFolder, @pA, pIgnoreDotFolders, pIgnoreDotFiles
   local tFiles, tFolders
   local tThisFolder
   if pIgnoreDotFolders is empty then
      put TRUE into pIgnoreDotFolders
   end if
   if pIgnoreDotFiles is empty then
      put TRUE into pIgnoreDotFiles
   end if

   put the defaultfolder into tThisFolder

   local tAbsFolder, tFoldersLeft, tSub
   set the defaultfolder to pFolder
   put the defaultfolder into tAbsFolder   -- changes relative into absolute

   put CR into tFoldersLeft
   repeat until tFoldersLeft is empty
      put line 1 of tFoldersLeft into tSub
      delete line 1 of tFoldersLeft
      set the defaultFolder to (tAbsFolder & tSub)
      if the result is not empty then
         -- skip or report as needed
         next repeat
      end if
      try
         put folders() into tFolders
      end try
      if pIgnoreDotFolders then
         filter tFolders without ".*"
      else
         filter tFolders without "."
         filter tFolders without ".."
      end if
      repeat for each line L in tFolders
         put tSub & "/" & L & CR after tFoldersLeft
      end repeat

      try
         put the detailed files into tFiles
      end try

      if pIgnoreDotFiles then
         filter tFiles without ".*"
      end if
      repeat for each line L in tFiles
         put item 2 to -1 of L into pA[pFolder & tSub][item 1 of L]
      end repeat
   end repeat
end getArrayOfFiles


_______________________________________________
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode

Reply via email to