В package require
линии действительно не займет гораздо больше времени, чем load
и source
вызовов, которые они делегируют (все пакеты делают, это останавливает вас от необходимости жесткого кода ко всем, заботясь обо всех деталях версий и т. д.). Однако,, когда вы делаете package require
пакета, имя которого еще не известно, Tcl должен фактически искать файлы pkgIndex.tcl
, которые описывают, как реально загружать пакеты. Он делает это, вызывая код, который вы можете найти (или при необходимости заменить), используя package unknown
, и это действительно очень медленно. В зависимости от содержимого переменной окружения это может быть чрезвычайно slow.
Но мы можем «скомпилировать» это, чтобы мы могли source
одного файла и иметь возможность загрузить эти конкретные пакеты на этом аппарате быстро.
Чтобы сделать это, нам нужны выше package require
с и немного дополнительного кода оберточной:
package require tlautils 1.0
package require profilemanager
package require tla::log 1.2
package require res_mgr 1.1
package require resource 1.2
package require sysexits
package require utils 1.5
package require testutil 1.0
package require profilemgr
package require leakChecker
package require testutil
set f [open "pkgdefs.tcl" w]
foreach pkg [package names] {
# Skip the packages built directly into Tcl 8.6
if {$pkg in {zlib TclOO tcl::tommath Tcl}} continue
# Get the actual loaded version; known but absent would be an error
if {[catch {package present $pkg} version]} continue
# Get the actual script that we'd run to load the package.
set script [package ifneeded $pkg $version]
# Add to the file
puts $f [list package ifneeded $pkg $version $script]
}
close $f
После того, как вы запустите, что вы будете иметь сценарий pkgdefs.tcl
, что вы можете source
. Если в будущем вы запустите вас source
, то до, совершив любой из этих package require
звонков, которые вы указали, звонки package require
будут быстрыми. (Это также включает в себя любые пакеты, которые являются зависимыми от тех, которые вы перечисляете.) Однако, если вы когда-либо устанавливаете новые пакеты для использования в списке или обновляете версии пакетов или перемещаете их, вам нужно будет перестроить list: он делает ваш код намного более негибким, поэтому мы не делаем его по умолчанию.
Я когда-то строил довольно большое приложение itcl. Я написал исходный файл, единственная цель которого заключалась в источнике или загрузке любых файлов, которые могут понадобиться, перед использованием приложения. Это позволяет использовать файлы 'pkgIndex.tcl', которые загружают пакеты только при необходимости и могут вызывать задержки, но, конечно, приложение было менее модульным. Я не помню, оказало ли это положительное влияние на производительность. Основная мотивация заключалась в том, чтобы избежать ошибок пакета во время выполнения. – b2vincent