首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以使用CompUnit模块来收集数据?

是否可以使用CompUnit模块来收集数据?
EN

Stack Overflow用户
提问于 2021-02-25 19:59:10
回答 3查看 115关注 0票数 9

我已经开发了a module for processing a collection of documents

运行一次软件就能收集到关于它们的信息。数据存储在称为%processed%symbols的两个结构中。需要对数据进行缓存,以便随后在同一组文档上运行软件,其中一些文档可以更改。(文档本身使用CompUnit modules进行缓存。

当前数据结构的存储/恢复如下:

代码语言:javascript
复制
# storing
'processed.raku`.IO.spurt: %processed.raku;
'symbols.raku`.IO.spurt: %symbol.raku;

# restoring
my %processed = EVALFILE 'processed.raku';
my %symbols = EVALFILE 'symbols.raku';

将这些结构输出到文件中可能会很慢,因为哈希会被解析来创建Stringified表单,而输入会很慢,因为它们正在重新编译。

它不打算检查缓存的文件,只是为了保存软件运行之间的状态。

此外,尽管这对我的用例来说不是问题,但这项技术通常不能使用,因为据我所知,Stringification (序列化)不适用于Raku闭包。

我想知道是否可以使用CompUnit模块,因为它们用于存储模块的编译版本。那么,它们也许可以用来存储数据结构的“编译”或“内部”版本?

已经有办法做到这一点了吗?

如果没有,有没有什么技术上的原因呢?

EN

回答 3

Stack Overflow用户

发布于 2021-02-25 20:45:18

(您很有可能已经尝试过这个方法,并且/或者它不适合您的用例,但我想我应该提一下,以防它对您或其他发现这个问题的人有帮助。)

您是否考虑过使用JSON::Fast将数据序列化到JSON和JSON之间?它已经针对(反)序列化速度进行了优化,以一种基本的字符串化还没有/不能做到的方式。这不允许存储Block或其他闭包-正如您所提到的,Raku目前没有一个很好的方法来序列化它们。但是,既然您提到这不是问题,那么JSON就有可能适合您的用例。

[编辑:正如您在下面指出的,这可能会使对某些Raku数据结构的支持变得更加困难。通过将数据类型指定为序列化步骤的一部分,通常(但并非总是)可以解决此问题:

代码语言:javascript
复制
use JSON::Fast;
my $a = <a a a b>.BagHash;
my $json = $a.&to-json;
my BagHash() $b = from-json($json);
say $a eqv $b # OUTPUT: «True»

对于更难用JSON表示的数据结构(比如那些具有非字符串键的数据结构)来说,这会变得更加复杂。JSON::Class模块也可能会有所帮助,但我还没有测试它的速度。]

票数 7
EN

Stack Overflow用户

发布于 2021-03-03 16:28:53

在看了其他答案和预编译代码后,我意识到我最初的问题是基于一个误解。

Rakudo编译器生成一个中间的“字节码”,然后在运行时使用。由于模块是用于编译目的的自包含单元,因此可以预编译它们。这个中间结果可以被缓存,从而极大地提高了Raku程序的速度。

当Raku程序use已经编译的代码时,编译器不会再次编译它。

我曾认为预编译缓存是程序内部状态的一种存储,但事实并非如此。这就是为什么--我想--@拉尔夫被这个问题搞糊涂了,因为我没有问对问题。

我的问题是关于数据的存储(和恢复)。JSON:: fast,正如@codesections所讨论的,它非常快,因为它是由Rakudo编译器在较低级别使用的,因此是高度优化的。因此,在恢复时重构数据将比恢复本机数据类型更快,因为较慢的速率决定步骤是从“磁盘”存储和恢复,而JSON执行得非常快。

有趣的是,我提到的CompUnit模块使用了低级JSON函数,这使得JSON::Fast变得如此快速。

我现在正在考虑使用优化的例程存储数据的其他方法,可能是使用压缩/归档模块。这将归结为最快的测试。JSON路由可能是最快的。

所以这个问题没有明确的答案,因为问题本身是“不正确的”。

票数 3
EN

Stack Overflow用户

发布于 2021-02-28 08:35:46

更新 @RichardHainsworth指出,我被他们的问题搞糊涂了,尽管我觉得这样回答应该会有帮助。根据他的反应,以及他决定不接受@codesection的答案,这是当时唯一的另一个答案,我得出结论,最好删除这个答案,以鼓励其他人回答。但现在Richard已经提供了一个很好的解决方案,我正在删除它,希望它现在更有用。

TL;DR不使用EVALFILE,而是将您的数据存储在一个模块中,然后使用use。有一些简单的方法可以做到这一点,这些方法对EVALFILE的改进最少,但却很有用。还有更复杂的方法可能会更好。

EVALFILE的一个小改进

我决定首先提出一个小的改进,这样你就可以巩固你在EVALFILE中的思维转变。它在两个方面都很小:

  • 它应该只需要几分钟就能实现。

EVALFILE.相比,

  • 它只给了你一个小小的改进

我建议您在真正实现我在第一节中描述的内容之前,适当地考虑这个答案的其余部分(它描述了更复杂的改进,可能会带来更大的回报,而不是这个小的改进)。我认为这一小的改进很可能被证明是多余的,而不仅仅是作为通往后面部分的心理桥梁。

编写一个程序,比如store.raku,创建一个模块,比如data.rakumod

代码语言:javascript
复制
use lib '.';
my %hash-to-store = :a, :b;
my $hash-as-raku-code = %hash-to-store .raku;
my $raku-code-to-store = "unit module data; our %hash = $hash-as-raku-code";
spurt 'data.rakumod', $raku-code-to-store;

(当然,我对.raku的使用过于简单。以上只是一种概念证明。)

这种形式的数据写入基本上与您当前的解决方案具有相同的性能,因此在这方面没有任何好处。

接下来,编写另一个使用它的程序,比如using.raku

代码语言:javascript
复制
use lib '.';
use data;
say %data::hash; # {a => True, b => True}

在模块中使用use需要编译它。因此,当您第一次使用这种方法而不是EVALFILE读取数据时,它不会更快,就像写入数据一样。但是对于后续的读取,它应该要快得多。(直到您下一次更改数据并必须重新构建数据模块。)

这一节也不涉及闭包串行化,这意味着你仍然在做一个可能不必要的数据写入阶段。

强化闭包;黑客攻击

可以扩展上一节的方法以包括闭包的字符串。

您只需要访问包含闭包的源代码;使用regex/parse提取闭包;然后将匹配写入数据模块。简单!;)

现在,我将跳过填写细节,部分原因是我再次认为这只是一座心理桥梁,并建议您继续阅读,而不是像我刚刚描述的那样尝试。

使用CompUnits

现在我们到达以下位置:

我想知道是否可以使用CompUnit模块,因为它们用于存储模块的编译版本。那么,它们也许可以用来存储数据结构的“编译”或“内部”版本?

我对你在这里问的问题有点困惑,原因有两个。首先,我认为您指的是文档(“文档本身是使用CompUnit模块缓存的”),并且文档被存储为模块。其次,如果您的意思是文档存储为模块,那么为什么不能存储您想要存储在其中的数据呢?您是否担心隐藏数据?

无论如何,我假定您正在询问有关在文档模块中存储数据的问题,并且您对“隐藏”该数据的方法感兴趣。

一个简单的选择是像我在第一节中所做的那样编写数据,但是在实际文档之后的末尾插入our %hash = $hash-as-raku-code"; etc代码,而不是在开头。

但也许这太丑陋了/还不够“隐藏”?

另一种选择可能是在文档模块的末尾添加带有Pod block configuration data的Pod块。

例如,将所有代码放入一个文档模块中,并抛出一个say作为概念验证:

代码语言:javascript
复制
# ...
# Document goes here
# ...

# At end of document:
=begin data :array<foo bar> :hash{k1=>v1, k2=>v2} :baz :qux(3.14)
=end data

say $=pod[0].config<array>; # foo bar

也就是说,这只是在模块中执行的代码;我不知道模块的编译形式是否保留了配置数据。此外,您还需要使用"Pod loader“(参见Access pod from another Raku file)。但我猜你对这些事情都很了解。

同样,这可能还不够隐蔽,而且还存在一些限制:

Hashs.或中,

  • 数据只能是StrIntNumBool类型的文字标量,或者是它们的聚合

  • 数据中不能有实际的换行符。(您可能有带\ns的双引号字符串。)

修改Rakudo

Aiui,假设RakuAST登陆,编写可以使用Raku模块执行任意工作的Rakudo插件将相对容易。从RakuAST宏到基本的is parsed宏似乎只有一小步之遥,而在编译器中提取源代码(例如闭包的源代码),然后将其作为数据输出到编译后的代码中似乎也是一小步,可能会附加到Pod声明符块中,而这些块又会作为代码附加到代码中。

因此,也许只需等待一两年,看看RakuAST是否会登陆并获得您需要的钩子,以便通过Rakudo完成您需要做的事情?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66368049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档