Should we make $_
no longer be is dynamic
in 6.d (plus provide mitigation for where it needs to be)?
#10
Comments
I'm in favor of the change. The "all magic vars are For any future Perl 6 compilers this will be an issue. It feels appropriate to design the language to be efficient if we're not really losing any practical benefit. Having $_ be dynamic by default is, in my experience, sometimes really handy and sometimes an annoying feature I have to work around. Lexical by default would simplify its usage by new Perl programmers. |
On Sonntag, 19. August 2018 15:05:40 CEST Jonathan Worthington wrote:
* The new pragma and export mechanism would need implementing, tests, docs,
etc. (I'd be willing to do that, but it's more that it's an ongoing cost,
like everything we add)
FWIW Inline::Perl5 already exports a "no precompilation" pragma, so that
functionality really is needed anyway:
https://github.com/niner/Inline-Perl5/blob/master/lib/Inline/Perl5.pm6#L800
|
going for speed now feels right to me |
Performance is incredibly important for Perl 6. I think a fast runtime is a much bigger selling point for Perl 5 programmers, than 5to6 migration modules could ever be. They probably wouldn't mind explicitly passing $_ to Perl 5 compatibility functions, or using Perl 6 methods instead, if that meant Perl 6 could be significantly faster, so I think the proposed mitigation pragma is not very important. |
Rakudo Perl 6 has a lot to offer to Perl 5 programmers: concurrency, nice OO, grammars, lots of built-in functions. These things are not in core Perl 5, so it's not like you can transpose Perl 5 constructs most of the time. Speed, next to the smaller ecosystem, is often of of the causes for some interested Perl 5 programmers not to use Perl 6 yet. |
Just a few questions/thoughts:
|
I agree with Juerd 110%. Its worth people explicitly passing $_ to Perl 5 compatibility functions in order for Perl 6 to gain performance, and its best to just make the change and not introduce a pragma. |
Don't know if it affects it, but FWIW there's some propspec that uses |
Thanks for all the comments. A few responses:
Unlikely, because none of the Perl 6 built-ins default to using the caller's
For a widely used feature, I think such a soft migration path would be more sensible. For one that seems barely used, it doesn't seem likely to help anyone.
Well, yes, there is a point here that if the Perl 5 compatibility modules export the pragma, then they enforce missed optimizations on code that uses them. I figure those are a porting aid, though, so behavioral similarity trumps speed.
Yes, I'll have to review those. Thanks. |
I wonder if this ticket was ever implemented? Current state of things is that Roast test |
Got a confirmation that |
Background
All of
$/
,$!
, and$_
default tois dynamic
. This means that they can be accessed throughCALLER::
and similar introspection features. For$/
, this is used heavily to set$/
from various bits of the regex matching mechanism. For$!
, I'm not aware of any current usages. For$_
, the only usage I'm aware of so far is in the variousP5
compatibility modules, which useCALLER::<$_>
in order to emulate the "works on$_
by default" semantics of the Perl 5 built-ins.Performance considerations
Consider
for ^10_000_000 { }
. This works by invoking the block with the current value, thus populating its$_
. In this case, the loop is optimized such that the iteration counter is done with native values, the boxing taking place in the parameter handling of the block.Ideally, we'd be able to see that the boxing is not required and eliminate it. Since boxing is a memory allocation of an object that then needs to be GC'd, that is potentially significant. Of course, we don't really care about it for the purpose of an empty loop body, which no real program would ever contain. But what if the loop does contain something? Can we be sure that it won't ever do
CALLERS::<$_>
?The immediate answer is, "as soon as we have late binding, then no". That means "as soon as we have a method call", for example. One might wonder if we can't just let inlining take care of matters: if the loop is hot enough, we will hopefully inline all of the things anyway, and then we can see what the code does. While that can indeed happen, it's not so simple. We do a lot of speculative optimization, with guard clauses triggering deoptimization. Just because our optimized code can never take a path where
CALLERS::<$_>
is used doesn't mean that it won't deopt and then find itself on a place where it is used.Another good question is, "but can't the upcoming work on partial escape analysis save us", and the answer is "yes, but..." We could:
This would work great for our microbenchmark here, and others where we manage to fully inline everything, or at least where the non-inlined path is taken rarely, so the
$_
only sometimes escapes. But forfor ^10_000_000 { $obj.some-very-big-method }
or similar, we'd not be able to do much apart from assume the worst.I've picked the
for
case as a concrete example, but$_
usage is incredibly widespread in idiomatic code:given $foo { }
with $bar { }
.map({ .foo + .bar })
And in all those we'll run into the same optimization challenges.
For
$/
and$!
, I'm not that concerned: the former would be swallowed up by the cost of regex handling anyway, and the latter only shows up in exceptional cases, which by definition are rarely taken.How much does this matter?
I believe the bar should be set pretty high for "we should change the language because X is hard to optimize". There's many things in Perl 6 that are challenging to make run fast, but we're making good progress on that anyway. To put this in to perspective, the current situation is that given these:
Then currently, measured on my none-too-fast home VM and using the experimental
postrelease-opts
version of MoarVM, we get:If we were to normalize for startup time, we'd be beating Ruby and within 1.3x of Perl 5 (but I don't really think we should be hiding our startup time, but rather improving it :)). But then consider:
Which runs in 0.261s. We should be able to optimize the range case in to this, and granted, with sufficiently smart PEA we'll be able to. But as noted, microbenchmarks are not representative of real programs, where "inline everything" isn't really realistic.
Usage of
$_
as a dynamicI'm only currently aware of use of
$_
being dynamic by the Perl 5 compatibility modules. I'm partly writing this to solicit input from those who may be aware of other cases that I have failed to consider. If that really is the only use of this feature, we might want to consider picking a more optimizable and analyzable default scope for$_
(e.g. "normal lexical").Mitigation for modules relying on
$_
as dynamicI'd propose in 6.d
use dynamic <$_>
or similar, for indicating that we want$_
to get dynamic scopeuse
r of the module (perhaps anEXPORTPRAGMA
to go withEXPORTHOW
or some such), so that the P5 compat modules can do that and require their users to do nothing different than they do todayFurther benefits
$_
the same way they consider their other lexicals: if you can't textually see it being changed and you aren't passing it somewhere, it won't be being changedDrawbacks
is dynamic
"The text was updated successfully, but these errors were encountered: