使用反射 $foo->$bar() 时性能中断
我想知道当我使用反射来调用一个名称为字符串的方法时到底发生了什么:
my $foo = Foo->new();
my $method = 'myMethod';
$foo->$method();
比本机调用慢约 20%:
$foo->myMethod();
任何指向有关如何实现 perl 反射的文档的指针都会有所帮助。
谢谢。
i'd like to know what exactly happens when i use reflection to call a method whose name i have as a string:
my $foo = Foo->new();
my $method = 'myMethod';
$foo->$method();
is ~20% slower than native call:
$foo->myMethod();
Any pointers to documentation about how perl's reflection is implemented would be helpful.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在第一个示例中,perl 必须加载
$bar
变量,然后检查它是否包含可用作方法的名称或值。由于$bar
的内容可能在调用之间发生变化,因此每次都必须执行此查找。在第二个示例中,perl 已经知道字符串
"bar"
应该用作方法名称,因此这可以避免加载变量并在每次执行时检查其内容。但您不必太担心两个本机操作之间 20% 的速度差异。主要是因为本机操作非常快,并且它们实际需要的任何速度很快就会与代码必须执行的实际算法相形见绌。换句话说,除非您使用代码分析器将此问题隔离为热点,否则速度差异的教学意义大于实际意义。
In the first example, perl has to load the
$bar
variable, and then check to see if it contains a name or value that can be used as a method. Since the contents of$bar
could change between calls, this lookup must be done each time.In the second example, perl already knows that the string
"bar"
should be used as a method name, so this avoids loading the variable and checking its contents on each execution.But you should not worry too much about a 20% percent speed difference between two native operations. Mainly because native operations are very fast, and any speed that they actually do require will quickly be dwarfed by the actual algorithm your code has to perform. In other words, unless you have isolated this issue as a hot spot with a code profiler, the speed difference has more pedagogical than practical importance.
首先,我不相信我没有看到的基准。很容易弄错他们。我自己对它们进行了基准测试。
我可以复制你的结果。
这看起来确实相当大,但百分比可能会因为如此快的速度而产生误导。让我们看看绝对时间的差异。
没那么多。那么这些时间都花在哪里了呢?
似乎唯一的区别是额外的符号表查找。 100ns 似乎有点过分了。但可以肯定的是,与一些微小的东西相比,比如添加一个。
将该代码和
our $x = 100;
插入上面的基准代码中,我们得到所以,
那么简单的符号表查找花费的时间是添加一个的两倍是否合理?可能是,因为它涉及对字符串进行哈希处理并在短链表中查找字符串。
你真的介意到处多花 100 纳秒吗?不,我猜。
First, I don't trust benchmarks I don't see. It's too easy to get them wrong. I benchmarked them myself.
I can replicate your results.
That does seem rather big, but percentages can be very misleading with something so fast. Let's look at the difference in absolute times.
Not that much. So where is that time spent?
It seems the only difference is an extra symbol table lookup. 100ns seems excessive for that. But to be sure, compare to something tiny, say like adding one.
Plugging that code and
our $x = 100;
into the benchmark code above, we getSo,
So is it reasonable for a simple symbol table lookup to take twice as long as adding one? Probably, since it involves hashing a string and looking for a string in short linked list.
Do you really care about spending an extra 100ns here and there? No, I'm guessing.
您可以通过使用方法引用来加速此过程,ala:
如果您在编译时知道方法名称,则显然可以使用 $metref = \&Class::myMethod 来代替。还有使用
sub { ... }
的闭包,perl 可能会比符号解除引用更有效地处理它们。请参阅此 perlmonks 讨论 和 perlref :制作参考。You could speed this up by using a method reference, ala :
You could obviously use
$metref = \&Class::myMethod
instead if you knew the method name at compile time. There are also closures usingsub { ... }
which perl might treat more efficiently than your symbolic dereferencing. See this perlmonks discussion and perlref : Making References.