capture - 像 Slurpy 一样使用 Capture
问题描述
我一直在阅读有关Captures的内容,这一段让我很感兴趣:
在签名中,可以通过在无符号参数前加上竖线 | 来创建捕获。这会将参数列表的其余部分打包到该参数中。
这听起来很像一个**@
(非扁平化)slurpy,所以这编造了这个测试代码:
my $limit=1_000_000;
my @a=1 xx 10000;
my @b=-1 xx 10000;
sub test1(|c){
1;
};
sub test2(**@c){
1;
};
{
for ^$limit {
test1(@b,@a);
}
say now - ENTER now;
}
{
for ^$limit {
test2(@b,@a);
}
say now - ENTER now;
}
样本运行给出了每个测试块的持续时间:
0.82560328
2.6650674
Capture 显然具有性能优势。以这种方式使用 aCapture
作为 slurpy 有不利的一面吗?我是否过度简化了比较?
解决方案
ACapture
有两个插槽,包含一个 VM 级别的数组(位置参数)和哈希(命名参数)。它的构造非常便宜,并且 - 由于|c
样式参数在内部的各个部分中都很常见 - 已经得到了很好的优化。由于捕获参数会同时占用位置参数和命名参数,因此任何命名参数都将被静默忽略。对于方法来说,这可能不是什么大问题,其中不需要的命名参数无论如何都会被静默放置%_
,但如果在 a 上使用此构造可能是一个考虑因素sub
,因为它不是纯粹的优化:它会改变行为。
该**@c
案例分配一个Array
,然后Scalar
为每个传递的值分配一个容器,将它们放入Scalar
容器中,将这些Scalar
容器放入Array
. 这是合理的额外工作量。
这里没有考虑另一种情况,就是这个:
sub test3(**@c is raw){
1;
}
这放置了一个List
in @c
,并将其元素设置为直接引用传递的内容。这比没有的情况要便宜一些is raw
。从理论上讲,它的性能可能与 - 如果不优于 - 捕获参数一样好,例如|c
; 它可能只需要有人在编译器上工作来深入了解为什么它还没有。
总之,如果不关心强制逐项和/或具有可变Array
的传入参数,那么添加is raw
可能是比选择捕获参数更好的优化选择:参数处理语义更接近,它已经有点快,将允许更多自然代码,并且未来有可能与|c
.
推荐阅读
- python - AttributeError:“模块”对象没有属性“液晶显示器”
- rest - WooCommerce rest api包括参数不获取可变产品的变化
- scala - 在 Scala 中计算素数流的代码
- java - 在java中重新分配其复制引用时更改原始对象
- c - sha512:使用 openSSL 库的 c 程序
- java - 设置从 JSON 文件中提取文件名的图像
- flutter - Flutter 中的异步 Listview 更新
- logstash - Logstash 过滤器插件作为文件
- c# - OnConfiguring DbContextOptionsBuilder 使我的数据库测试失败
- java - Android Studio,缺少 android.support.annotation 包