我试图通过使用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;
因此,现在我更改POD,如何使用:since
标志?我认为,如果:since
在编译后包含一个时间,则该句柄的值为Nil。似乎并非如此。
my $new-handle = $precomp.load($key, :since('test.pod6'.IO.modified));
say 'I got a new handle' with $new-handle;
输出为“我有一个新手柄”。
我做错了什么? 这是一个带代码和输出的pastebin链接:https://pastebin.com/wtA9a0nP
答案 0 :(得分:4)
模块加载代码缓存查找并从以下开始:
$lock.protect: {
return %loaded{$id} if %loaded{$id}:exists;
}
因此问题变成“我如何加载模块然后卸载它(以便我可以再次加载它)?”?答案是:您不能卸载模块。但是,您可以更改文件名,分发长名称(通过更改名称,auth,api或版本)或precomp id(无论使用什么CompUnit :: Repository来唯一标识模块),以绕过缓存。
似乎被忽略的是$key
旨在表示一个不变的名称,因此它总是指向相同的内容。如果模块{{1}同时由模块foo.pm
和Used::Inside::A
加载foo.pm
,则应为模块A
加载哪个版本的B
}首先加载foo,然后模块A
修改foo?加载了旧版本的模块B
,或者(可能与先前版本冲突)加载了模块B?以及这种区别如何对precomp文件生成本身起作用(这又可以并行发生)?
当然,如果我们忽略上述内容,则可以添加代码以使所有CompUnit :: Repository类型的每个模块加载都进行昂贵的A
调用,以说“嘿,这个不变的东西已经改变了” 。但是文件系统修改的时间戳在某些操作系统上的粒度使检查变得非常脆弱(尤其是对于生成带有precomp文件的多线程模块加载),这意味着每次都需要更昂贵的调用来获取校验和。>