我试图通过使用CompUnit类集预编译来创建POD6的缓存.
我可以创建,存储和检索pod,如下所示:
use v6.c;
use nqp;
my $precomp-store = CompUnit::PrecompilationStore::File.new(prefix=>'cache'.IO);
my $precomp = CompUnit::PrecompilationRepository::Default.new(store=> $precomp-store );
my $key = nqp::sha1('test.pod6');
'test.pod6'.IO.spurt(q:to/CONTENT/);
=begin pod
=TITLE More and more
Some more text
=end pod
CONTENT
$precomp.precompile('test.pod6'.IO, $key, :force);
my $handle = $precomp.load($key, )[0];
my $resurrected = nqp::atkey($handle.unit,'$=pod')[0];
say $resurrected ~~ Pod::Block::Named;
Run Code Online (Sandbox Code Playgroud)
所以现在我改变POD,我该如何使用:since旗帜?我认为如果:since在编译后包含一段时间,那么句柄的值将为Nil.情况似乎并非如此.
my $new-handle = $precomp.load($key, :since('test.pod6'.IO.modified));
say 'I got a new handle' with $new-handle;
Run Code Online (Sandbox Code Playgroud)
输出是'我有一个新手柄'.
我做错了什么?这是一个包含代码和输出的pastebin链接:https://pastebin.com/wtA9a0nP
模块加载代码缓存查找,本质上是从以下开始:
$lock.protect: {
return %loaded{$id} if %loaded{$id}:exists;
}
Run Code Online (Sandbox Code Playgroud)
所以问题变成了“如何加载模块然后卸载它(这样我可以再次加载它)?” 答案是:您无法卸载模块。但是,您可以更改文件名、分发长名称(通过更改名称、身份验证、api 或版本)或预编译 ID(无论特定 CompUnit::Repository 使用什么来唯一标识模块),以绕过缓存。
似乎被忽视的是,它$key旨在表示一个不可变的名称,以便它始终指向相同的内容。如果Module正在加载,并且Module先加载foo,然后Module修改foo ,那么Modulefoo.pm应该加载什么版本?旧版本模块Used::Inside::Afoo.pmABABA,还是(可能与以前的版本冲突)模块 B 加载的版本?这种差异如何用于预编译文件生成本身(这又可以并行发生)?
当然,如果我们忽略上述内容,我们可以添加代码,.IO.modified对所有 CompUnit::Repository 类型的每个模块加载进行昂贵的调用(减慢启动速度),以表示“嘿,这个不可变的东西发生了变化”。但是某些操作系统上文件系统修改时间戳的粒度使得检查非常脆弱(特别是对于生成预编译文件的多线程模块加载),这意味着每次都需要更昂贵的调用来获取校验和。