在 perl 5 中,您可以wc -l使用 oneliner进行模拟:
perl -lnE 'END {say $.}' test.txt
如何在 Raku 上实现此功能
如果您尝试实现这一点:
raku -e 'say "test.txt".IO.open.lines.elems'
事实证明它很慢并且使用了大量内存
重现的信息:
$ wget http://eforexcel.com/wp/wp-content/uploads/2017/07/1500000%20Sales%20Records.zip
$ unzip "1500000 Sales Records.zip"
$ mv "1500000 Sales Records.csv" part.txt
$ for i in `seq 1 10`; do cat part.txt >> test.txt ; done
$ du -sh test.txt
1.8G test.txt
$ time wc -l test.txt
15000000 test.txt
real 0m0,350s
user 0m0,143s
sys 0m0,205s
$ time perl -lnE 'END { say $. }' test.txt
15000001
real 0m1,981s
user 0m1,719s
sys 0m0,256s
$ time raku -e 'say "test.txt".IO.open.lines.elems'
15000001
real 2m51,852s
user 0m25,129s
sys 0m6,378s
# Using swap (maximum uses 2.2G swap):
# Before `raku -e ''`
$ free -m
total used free shared buff/cache available
Mem: 15009 1695 12604 107 708 12917
Swap: 7583 0 7583
# After `raku -e ''`
$ free -m
total used free shared buff/cache available
Mem: 15009 752 13923 72 332 13899
Swap: 7583 779 6804
# Swap not used
$ time raku -ne '++$ andthen END .say' test.txt
15000001
real 1m44,906s
user 2m14,165s
sys 0m0,653s
$ raku -v
This is Rakudo version 2019.11 built on MoarVM version 2019.11
implementing Perl 6.d.
Run Code Online (Sandbox Code Playgroud)
与以下相比,仍然可能很慢perl但值得比较的一种选择:
raku -ne '++$ andthen END .say' test.txt
Run Code Online (Sandbox Code Playgroud)
该l命令行选项是多余的。
$ 是匿名状态标量。
andthen测试其 lhs 是否已定义,如果已定义,则将该值设置为主题 ( $_),然后评估其 rhs。
END类似于perl的END。请注意,它返回Nil到 ,andthen但这在这里无关紧要,因为我们使用END's 语句来实现它的副作用。
有几件事会影响此代码的速度。我能想到的一些事情:
编译器启动开销。忽略正在使用的任何模块,raku编译器 Rakudo 在典型硬件上的启动开销约为十分之一秒,而perl.
“线”的概念。在 中perl,行处理的默认概念是读取一系列字节,其中一些字节代表行结束。在 中raku,行处理的默认概念是读取 UTF-8 字符串,其中一些表示行结束。因此perl只会产生 ASCII(或扩展 ASCII)解码器raku的读取开销,而产生 UTF-8 解码器的读取开销。
编译器优化。 perl通常优化到最大值。如果perl -lnE 'END {say $.}' test.txt利用一些巧妙的优化,我不会感到惊讶。相比之下,Rakudo 优化的工作相对来说还处于起步阶段。
对于我上面提到的三点中的第一点和最后一点,我认为任何人都可以做的唯一事情就是等待 N 年和/或为编译器的改进做出贡献。
将有一种方法可以解决 raku 默认的 UTF-8。也许像下面这样的东西已经是可行的,并且比 raku 的默认值快得多,至少忽略使用名为 的模块的开销foo:
raku -Mfoo -ne '++$ andthen END .say' test.txt
Run Code Online (Sandbox Code Playgroud)
其中 modulefoo将文件 I/O 的默认编码切换为 ASCII 或可用编码中的任何内容。
我还没有检查过这在当前的 Rakudo 中实际上是可行的,但如果不是,我会感到惊讶。
| 归档时间: |
|
| 查看次数: |
227 次 |
| 最近记录: |