Thread from comp.lang.tcl (3 replies)

How to speed up a script by threading?
Posted by Mark Summerfield <mark@qtrac.eu> 2 months 2 weeks ago

The program below (~95 LOC) is very slow.
One way to speed it up would be to process each directory given on the 
command line in its own thread.
But I can't see how to do this.
Or is there a better way to make it faster?
I'm using Tcl/Tk 9.0b2 on Linux.

#!/usr/bin/env tclsh9

package require fileutil 1

namespace eval ef {}

proc ef::main {} {
    lassign [read_args] patterns dirs debug ;# may not return
    if {$debug} {
        puts "globs='$patterns'"
    }
    set filenames [list]
    foreach dir $dirs {
        if {$debug} {
            puts "folder='$dir'"
        }
        foreach filename [fileutil::findByPattern $dir $patterns] {
            lappend filenames $filename
        }
    }
    foreach filename [lsort $filenames] {
        puts $filename
    }
}

proc ef::read_args {} {
    set what ""
    set dirs [list]
    set debug false
    foreach arg $::argv {
        switch $arg {
            -h -
            --help {usage}
            -D -
            --debug {set debug true}
            default {
                if {$what eq ""} {
                    set what $arg
                } else {
                    lappend dirs $arg
                }
            }
        }
    }
    if {$what eq ""} {
        usage
    }
    set patterns [get_patterns $what]
    if {![llength $dirs]} {
        lappend dirs .
    }
    return [list $patterns $dirs $debug]
}

proc ef::usage {} {
    puts $::USAGE
    exit 1
}

proc ef::get_patterns what {
    if {[string index $what 0] ne "."} {
        return "*$what*"
    }
    set patterns [list *$what]
    switch $what {
        .c {lappend patterns *.h}
        .c++ {lappend patterns *.h *.hxx *.hpp *.h++ *.cxx *.cpp}
        .cpp {lappend patterns *.h *.hxx *.hpp *.h++ *.cxx *.c++}
        .tcl {lappend patterns *.tm}
        .py {lappend patterns *.pyw}
    }
    return $patterns
}

const USAGE {usage: efind.tcl [options] <what> [dir1 [dir2 …]]

options:
-h, --help      Show this usage message and quit.
-D, --debug     Show pattern and folders being processed.

Searches for files that match \"what\" in . or in any specified
folders, including recursively into subfolders.
\"what\" is either \".ext\" or text, e.g., .tcl or .py; or go.mod;
for .tcl searches *.{tcl,tm}, for .py *.{py,pyw}, for .c *.{c,h}
for .cpp or .c++ *.{h,hxx,hpp,h++,cxx,cpp,c++}; others as is.}

ef::main

Click on article to view all threads in comp.lang.tcl
Re: How to speed up a script by threading?
Posted by Ralf Fassel <ralfixx@gmx.de> 2 months 2 weeks ago

* Mark Summerfield <mark@qtrac.eu>
| The program below (~95 LOC) is very slow.
| One way to speed it up would be to process each directory given on the 
| command line in its own thread.
| But I can't see how to do this.
| Or is there a better way to make it faster?
| I'm using Tcl/Tk 9.0b2 on Linux.

Since you give the directories on the (linux) commandline, put the
one-thread-per-dir one level up:

Instead of
  your-prog dir1 dir2 dir3 ...
do
  for dir in dir1 dir2 dir3 ... ; do
    your-prog $dir &
  done

That way multiple processes (not threads) run in parallel,
and you don't have to change the program at all.

My 0.02.
R'

Click on article to view all threads in comp.lang.tcl
Re: How to speed up a script by threading?
Posted by Harald Oehlmann <wortkarg3@yahoo.com> 2 months 2 weeks ago

Am 19.07.2024 um 10:14 schrieb Mark Summerfield:
> The program below (~95 LOC) is very slow.
> One way to speed it up would be to process each directory given on the
> command line in its own thread.
> But I can't see how to do this.
> Or is there a better way to make it faster?
> I'm using Tcl/Tk 9.0b2 on Linux.
> 
> #!/usr/bin/env tclsh9
> 
> package require fileutil 1
> 
> namespace eval ef {}
> 
> proc ef::main {} {
>      lassign [read_args] patterns dirs debug ;# may not return
>      if {$debug} {
>          puts "globs='$patterns'"
>      }
>      set filenames [list]
>      foreach dir $dirs {
>          if {$debug} {
>              puts "folder='$dir'"
>          }
>          foreach filename [fileutil::findByPattern $dir $patterns] {
>              lappend filenames $filename
>          }
>      }
>      foreach filename [lsort $filenames] {
>          puts $filename
>      }
> }
> 
> proc ef::read_args {} {
>      set what ""
>      set dirs [list]
>      set debug false
>      foreach arg $::argv {
>          switch $arg {
>              -h -
>              --help {usage}
>              -D -
>              --debug {set debug true}
>              default {
>                  if {$what eq ""} {
>                      set what $arg
>                  } else {
>                      lappend dirs $arg
>                  }
>              }
>          }
>      }
>      if {$what eq ""} {
>          usage
>      }
>      set patterns [get_patterns $what]
>      if {![llength $dirs]} {
>          lappend dirs .
>      }
>      return [list $patterns $dirs $debug]
> }
> 
> proc ef::usage {} {
>      puts $::USAGE
>      exit 1
> }
> 
> proc ef::get_patterns what {
>      if {[string index $what 0] ne "."} {
>          return "*$what*"
>      }
>      set patterns [list *$what]
>      switch $what {
>          .c {lappend patterns *.h}
>          .c++ {lappend patterns *.h *.hxx *.hpp *.h++ *.cxx *.cpp}
>          .cpp {lappend patterns *.h *.hxx *.hpp *.h++ *.cxx *.c++}
>          .tcl {lappend patterns *.tm}
>          .py {lappend patterns *.pyw}
>      }
>      return $patterns
> }
> 
> const USAGE {usage: efind.tcl [options] <what> [dir1 [dir2 …]]
> 
> options:
> -h, --help      Show this usage message and quit.
> -D, --debug     Show pattern and folders being processed.
> 
> Searches for files that match \"what\" in . or in any specified
> folders, including recursively into subfolders.
> \"what\" is either \".ext\" or text, e.g., .tcl or .py; or go.mod;
> for .tcl searches *.{tcl,tm}, for .py *.{py,pyw}, for .c *.{c,h}
> for .cpp or .c++ *.{h,hxx,hpp,h++,cxx,cpp,c++}; others as is.}
> 
> ef::main

Hi Mark,

great that you are so active. The tootip stuff is sorted out and all 
issues are corrected, thank you for that.

The diagram issue is open.

About threads, you may use threads with TCL using the Thread package. 
That is again a long story. You first need the normally bundled 
extension "thread" (package require thread). Then you can create threads 
and charge trhem with TCL scripts and get the results together.

Harald



Click on article to view all threads in comp.lang.tcl
Re: How to speed up a script by threading?
Posted by saito <saitology9@gmail.com> 2 months 2 weeks ago

On 7/19/2024 5:08 AM, Ralf Fassel wrote:
> * Mark Summerfield <mark@qtrac.eu>
> | The program below (~95 LOC) is very slow.
> | One way to speed it up would be to process each directory given on the
> | command line in its own thread.
> | But I can't see how to do this.
> | Or is there a better way to make it faster?
> | I'm using Tcl/Tk 9.0b2 on Linux.
> 
> Since you give the directories on the (linux) commandline, put the
> one-thread-per-dir one level up:
> 

On linux, it might be easier to just do "find"; it is quite fast.

Click on article to view all threads in comp.lang.tcl