• How to speed up a script by threading?

    From Mark Summerfield@21:1/5 to All on Fri Jul 19 08:14:38 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Fri Jul 19 11:08:14 2024
    * 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'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Harald Oehlmann@21:1/5 to All on Fri Jul 19 12:04:59 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)