Welcome to the main channel on the development of MoarVM, a virtual machine for NQP and Rakudo (moarvm.org). This channel is being logged for historical purposes. Set by lizmat on 24 May 2021. |
|||
00:13
MasterDuke91 joined
|
|||
MasterDuke91 | timo: you might find github.com/Raku/nqp/commit/0d4885d...e43b98d7d7 interesting | 00:13 | |
timo | well, that disappeared | 00:19 | |
MasterDuke91 | yep | ||
timo: with your change, `raku --ll-exception -e 'use MONKEY; say EVAL "die";'` gives: | 00:21 | ||
Died | |||
at gen/moar/CORE.c.setting:49703 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:throw) | |||
from gen/moar/CORE.c.setting:1015 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:die) | |||
from gen/moar/CORE.c.setting:1011 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:die) | |||
without that change: | 00:22 | ||
Died | |||
at SETTING::src/core.c/Exception.pm6:62 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:throw) | |||
from SETTING::src/core.c/control.pm6:213 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:die) | |||
from SETTING::src/core.c/control.pm6:209 (/home/dan/Source/perl6/install/share/perl6/runtime/CORE.c.setting.moarvm:die) | |||
timo | i need to revert that | 00:24 | |
we may want to see if we can optimize that. a lot, ideally | 00:26 | ||
MasterDuke91 | please do | 00:27 | |
timo | so during parsing, we hit mostly the first entry in the list or the last | 01:11 | |
while going through the mast stage however we kind of just linearly go from the start to the end, where the list is 228 entries long | 01:12 | ||
some kind of little cache could probably do a lot to help here | |||
perhaps splitting the directives array into one array of line numbers and one with filenames | 01:13 | ||
so we dont have a bunch of nested lists of int, str in the directives list | 01:14 | ||
so the line numbers list can become a native int list as well | |||
native str list is a little better than regular list with strings in it as well i think? | |||
additionally / alternatively, there could be a binary search there | 01:15 | ||
01:24
evalable6 left,
linkable6 left
01:27
linkable6 joined
01:55
kjp left
01:56
kjp joined
03:25
evalable6 joined
04:00
MasterDuke91 left
04:05
reportable6 joined
04:25
Xliff left
05:33
committable6 left,
statisfiable6 left,
greppable6 left,
sourceable6 left,
releasable6 left,
linkable6 left,
evalable6 left,
squashable6 left,
bisectable6 left,
shareable6 left,
bloatable6 left,
nativecallable6 left,
unicodable6 left,
benchable6 left,
notable6 left,
coverable6 left,
quotable6 left,
tellable6 left,
reportable6 left,
unicodable6 joined
05:34
evalable6 joined,
nativecallable6 joined,
coverable6 joined,
tellable6 joined
05:35
greppable6 joined
05:36
committable6 joined,
shareable6 joined
05:39
Altai-man left
06:03
reportable6 joined
06:34
sourceable6 joined,
linkable6 joined
06:35
quotable6 joined
06:36
benchable6 joined,
notable6 joined,
bloatable6 joined,
squashable6 joined
06:56
frost joined
|
|||
Nicholas | good *, #moarvm | 07:12 | |
07:36
bisectable6 joined,
statisfiable6 joined
08:36
releasable6 joined
|
|||
timo | good | 08:41 | |
lizmat switched back to the new-disp branch | 08:59 | ||
and did some test-t timing: master: 1.32 / 0.60 (test-t and test-t --race | 09:00 | ||
new-disp: 2.11 / 0.81 | 09:01 | ||
startup: .12 (master) and .16 (new-disp) | 09:02 | ||
just some data points... no pressure :-) | |||
Nicholas | I'm sure it's all brrt's fault for not JITting it all yet :-) | 09:07 | |
lizmat | while doing some timing stuff, something struck me (again) that I feel warrants some thinking | 09:08 | |
when just measuring bare startup, every now and then I get an outlier that is *way* below average | 09:09 | ||
just now, on master: 5 times .126 in a row, and then one with .095 | 09:10 | ||
and I can't help but think: maybe that outlier didn't have its spesh thread started for some reason | 09:11 | ||
is that a weird idea? | |||
or are there other easy ways to all of a sudden get a much faster startup ? | 09:12 | ||
(well, and shutdown of course) | |||
timo | it would be quite strange for the spesh thread to not start | 09:20 | |
Nicholas | lizmat: to paraphrase the Spacex reddit answer of "it's ice. it's always ice" (which isn't quite always true) we always seem to say "it's hash randomisation, and it's causing spesh to have a good day" (or bad day). As in | ||
I'd suggest that, but I have no idea how to test that theory | 09:21 | ||
timo | but i'm also not entirely sure if we're perhaps waiting a noticeably long time for the process to shut down due to the spesh thread? | ||
we can systematically test one bajillion hash randomization seeds, right? | |||
Nicholas | In parallel universes in constant time, sure. But it's probably faster to test about 100 runs (or whatever it is) with hash randomisation "normal", and then try 100 with it disabled (or fixed to one salt) and see if the latter doesn't have these outliers | 09:22 | |
lizmat | if it *is* hash randomization, then from the bajillion possible seeds, maybe we could choose from a subset that is faster 30% faster :-) | ||
how does one start up with it disabled again ? | 09:23 | ||
timo | oh i thought that was a compile time change | 09:24 | |
Nicholas | er, I'm not sure if it's possible without changing a #define and recompiling MoarVM. | ||
lizmat | ah... ok | ||
Nicholas | and there were actually two things to disable | 09:25 | |
1) the random 64 bit value used to peturb the calls to SIPhash generating the 64 bit hash value for any string | |||
2) the random number in each hash that gets "mixed" into that | |||
09:33
lizmat_ joined
09:37
lizmat left,
lizmat_ is now known as lizmat,
lizmat left,
lizmat joined
|
|||
timo | so, um, who knows how moar and nqp handle nonexistant dynamic variables, why do they get a list when they are @ sigiled and why do you get the same list back every time? | 09:44 | |
lizmat only knows of the Rakudo way :-( | 09:45 | ||
jnthnwrthngtn | I believe NQP also has some kind of fallback semantics | 10:19 | |
lizmat: The test-t one is very likely mostly down to the missing inlining still. | 10:20 | ||
lizmat: I'm continuing work on that today; we'll see how far I get | |||
Startup is a thornier issue. | |||
lizmat | ++jnthnwrthngtn :-) | 10:21 | |
jnthnwrthngtn | We do save on deserializing method caches, but we probably make that up in deserializing meta-objects. | 10:23 | |
Although deserialization is by far dominated by the inefficient way NFAs are stored | 10:24 | ||
lizmat | what could be done to store them more efficiently? | ||
timo | we currently store them both as a bunch of arrays and an actual nfa object | ||
the nfa object has essentially its own optimized serialization | 10:25 | ||
and you can relatively easily make the one form from the other | |||
jnthnwrthngtn | Right, if we could recover the bunch of arrays from the NFA object that'd be a kinda solution but... | ||
timo | did the branch where i implemented that nqp op ever get merged, i wonder | ||
jnthnwrthngtn | ...when I glanced "how much effort is this" it seemed one'd have to restructure quite a bit of the code too | ||
timo | yeah, we need the bunch-of-arrays form so that we can modify the nfa from nqp code | 10:26 | |
jnthnwrthngtn | Then I was like, sigh, we need to re-work the grammar engine more broadly, so this is annoying throwaway work | ||
lizmat | which brings me back to the idea I once had, of reimplementing the grammar engine in Rakudo :-) | ||
timo | surely we can't just make an nfa multi-dim-subscriptable? | ||
jnthnwrthngtn | timo: That's...interesting | 10:27 | |
timo | probably troublesome for in-between forms while we're modifying stuff | ||
jnthnwrthngtn | lizmat: For prototyping a new design, or as the thing to use? | 10:28 | |
(It'd present some...bootstrapping problems...if the latter.) | |||
lizmat | potentially both ? | ||
jnthnwrthngtn | I mean, we'd want to use it for NQP too | ||
For prototyping it makes sense at least. | 10:29 | ||
timo | clearly needs a raku to nqp compiler :) | ||
jnthnwrthngtn | I already have a terrible partial one of those :P | ||
(That's what the AST implementation does.) | |||
lizmat | he.. indeed :-) | 10:30 | |
timo | yup | 10:33 | |
nqp-js: sub a() { say(nqp::objectid(@*a)); }; sub m() { say(nqp::objectid(@*a)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | 10:35 | ||
camelia | sudo: /home/camelia/nqp-js: command not found | ||
timo | nqp-jvm: sub a() { say(nqp::objectid(@*a)); }; sub m() { say(nqp::objectid(@*a)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | ||
camelia | sudo: /home/camelia/rakudo-j-inst/bin/nqp-j: command not found | ||
timo | nqp: sub a() { say(nqp::objectid(@*a)); }; sub m() { say(nqp::objectid(@*a)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | 10:36 | |
camelia | 21030072 21030072 21030072 21030072 21030072 21030072 21030072 21030072 |
||
timo | jnthn, would you consider this a bug? | ||
nothing declares this dyn var but still we somehow store it somewhere? | |||
jnthnwrthngtn | Can you say .HOW.name of the thing given to objectid too? | 10:43 | |
(My suspicion is that it's NQPMu) | |||
timo | nqp: sub a() { say(nqp::objectid(@*a)); say(@*a.HOW.name(@*a)) }; sub m() { say(nqp::objectid(@*a)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | 10:45 | |
camelia | 45652648 NQPArray 45652648 NQPArray 45652648 NQPArray 45652648 45652648 45652648 45652648 NQPArray 45652648 |
||
timo | well there we have that | ||
nqp: sub a() { say(nqp::objectid(@*a)); say(@*a.HOW.name(@*a)) }; sub m() { say(nqp::objectid(@*b)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | 10:46 | ||
camelia | 42068920 NQPArray 42068920 NQPArray 42068920 NQPArray 42069536 42069536 42069536 42068920 NQPArray 42069536 |
||
jnthnwrthngtn | Is it a concrete array or just the type object? | ||
If the former, what on earth... | |||
timo | nqp: sub a() { say(nqp::objectid(@*a)); say(@*a.HOW.name(@*a)); say(nqp::isconcrete(@*a)) }; sub m() { say(nqp::objectid(@*b)); }; sub x() { a(); m(); }; a(); a(); x(); m();m(); a(); m(); | ||
camelia | 40005000 NQPArray 1 40005000 NQPArray 1 40005000 NQPArray 1 40005616 40005616 40005616 40005000 NQPArray 1 40005616 |
||
timo | concrete | ||
my thought is the mechanism that gives us an array when the dyn var doesnt exist since we asked for a @ sigil is somehow wonky | 10:47 | ||
jnthnwrthngtn | Yeah, I'm just wondering where on earth it stores it | 10:48 | |
$ast := QAST::VarWithFallback.new( | 10:49 | ||
:name(~@name.pop), :scope('contextual'), | |||
:fallback($global_fallback) | |||
); | |||
And $global_fallback involves | |||
lexical_package_lookup(['GLOBAL', ~$<sigil> ~ $<desigilname>], $/), | |||
Yeah, that does indeed vivify it in GLOBAL | 10:50 | ||
m: say(GLOBAL.WHO<@a>); @*a; say(GLOBAL.WHO<@a>); | 10:51 | ||
camelia | (Any) Dynamic variable @*a not found in block <unit> at <tmp> line 1 |
||
jnthnwrthngtn | oh, NQP | 10:52 | |
nqp: say(GLOBAL.WHO<@a>); @*a; say(GLOBAL.WHO<@a>); | |||
camelia | |||
jnthnwrthngtn | nqp: say(nqp::existskey(GLOBAL.WHO, '@a')); @*a; say(nqp::existskey(GLOBAL.WHO, '@a')); | ||
camelia | 0 0 |
||
jnthnwrthngtn | nqp: say(nqp::existskey(GLOBAL.WHO, '@*a')); @*a; say(nqp::existskey(GLOBAL.WHO, '@*a')); | ||
camelia | 0 0 |
||
jnthnwrthngtn | nqp: say(nqp::existskey(GLOBAL.WHO, '@*a')); say(nqp::objectid(@*a)); say(nqp::existskey(GLOBAL.WHO, '@*a')); | 10:53 | |
camelia | 0 21036176 0 |
||
jnthnwrthngtn | nqp: say(nqp::existskey(GLOBAL.WHO, '@a')); say(nqp::objectid(@*a)); say(nqp::existskey(GLOBAL.WHO, '@a')); | ||
camelia | 0 47254240 0 |
||
jnthnwrthngtn | Huh. | ||
No idea, but yeah, agree that it vivifying an array is wrong | 10:54 | ||
lizmat | afk for a few hours& | 10:58 | |
10:59
squashable6 left
11:05
lizmat left
11:08
TempIRCLogger left
11:09
lizmat joined
11:10
TempIRCLogger joined
11:26
brrt joined
|
|||
Nicholas | good *, brrt | 11:50 | |
timo | bood *, grrt | 11:54 | |
12:00
squashable6 joined
12:03
reportable6 left
12:13
brrt left
|
|||
timo | now i can look where the right spot to hang the comp line directives is | 12:19 | |
its really at the compunit level i think? | |||
and the same spot that gets that would also get the tiny cache to make lookups fastered | 12:20 | ||
13:05
reportable6 joined
|
|||
jnthnwrthngtn | Getting somewhere with inlining calls with resumptions set up; it will find such a resumption and it works with the interp, but not with the JIT | 13:16 | |
It seems finding the current active deopt index doesn't work if we're in the frame on the stack top | |||
timo | does the resumption op need an annotation in the oplist that causes some varABle to get updated when its reached? | 13:19 | |
jnthnwrthngtn | m: say 0x7f590e8eb82b - 0x7f590e8eb337 | 13:21 | |
camelia | 1268 | ||
jnthnwrthngtn | No, it should really give the label immediately after the sp_dispatch that wants to resume, but doesn't | 13:23 | |
That first number is what it probably should find, the second is what is in *tc->jit_return_address | 13:24 | ||
13:24
frost left
13:25
brrt joined
|
|||
brrt | good *, timo, Nicholas | 13:25 | |
jnthnwrthngtn | oh yay, it's brrt :) | ||
brrt | also, I learnt recently that hacker news has a 'brnt' user, also from the Netherlands | ||
ohai jnthnwrthgtn.... I fear something is broken about the JIT again | 13:26 | ||
:-) | |||
jnthnwrthngtn | brrt: I'm having trouble getting MVM_jit_code_get_active_deopt_idx to give a valid result when it's about the currently executing frame | 13:27 | |
brrt: We're running an sp_dispatch at the time. I first though it was 'cus that wasn't marked :invokish, but I just tried that. | |||
brrt | ehm. | 13:28 | |
hmm | |||
jnthnwrthngtn | The piece I don't really understand: in the prologue we do: | ||
| lea rax, [rsp-0x8]; | |||
| mov aword TC->jit_return_address, rax; | 13:29 | ||
And null it out in the epilogue, but what is it that actually updates that location? | |||
Is it the `call` instruction, 'cus it's the (ABI-level) location of the return address? | |||
brrt | yes | ||
the 'call' instruction does this | 13:30 | ||
that's... the beauty of it, really | |||
this can go wrong if we use `push` and `pop` in the assembly | |||
which I don't think we do? | |||
jnthnwrthngtn | doesn't look liek it | 13:31 | |
github.com/MoarVM/MoarVM/blob/new-.../emit.dasc is the JIT of sp_dispatch | |||
In theory the label is right after it | |||
brrt will have a look | 13:33 | ||
jnthnwrthngtn | Oh. Uhhh. | ||
When we inline something...there isn't a DEOPT_ALL on it any more | 13:34 | ||
I wonder if that in turn means no label. | |||
brrt | two steps back pls | 13:35 | |
what lines should I be looking at | |||
jnthnwrthngtn | hah, yes, I figured out a fix | 13:38 | |
brrt | :-) | ||
jnthnwrthngtn | brrt: Today in after_ins we have: | ||
brrt | good. | ||
jnthnwrthngtn | } else if (ann->type == MVM_SPESH_ANN_DEOPT_ALL_INS) { | 13:39 | |
brrt | yeah | ||
jnthnwrthngtn | If I change it to | ||
} else if (ann->type == MVM_SPESH_ANN_DEOPT_ALL_INS || | |||
(ann->type == MVM_SPESH_ANN_DEOPT_INLINE && (ins->info->jittivity & MVM_JIT_INFO_INVOKISH))) { | |||
Then it works for inlines also, although this feels mildly cheaty | |||
I guess my next question is "how did we get away with this"... :) | 13:41 | ||
Geth | MoarVM/new-disp: dfde811154 | (Jonathan Worthington)++ | 3 files Ensure we have JIT deopt info for inlined dispatch * Mark it invokish * When we see an inline deopt annotation on an invokish instruction, treat it like a deopt all |
13:57 | |
brrt | ugh | 13:59 | |
I promise I probably knew one time | |||
timo | looking very forward to the next commit that i assume will be spesh linking and possibly inlining of things that use resumption | 14:01 | |
jnthnwrthngtn | We already have spesh linking of that, it's inlining | 14:04 | |
I do locally have the first step to reinstating inlining working, but: | |||
1. I know I need to do a bit more work with regard to deopt, but it's surprisingly tricky to write an example that triggers it | |||
(And still does all the required inlines, and triggers it at the right time to make the situation that needs handling) | 14:05 | ||
2. I see a couple of spectest regressions, although they don't involve resumption, so I think I'm allowing more inlining and exposing something else that wants fixing | |||
I'd like to sort out 1 before I push it | 14:06 | ||
timo | phew. okay | ||
jnthnwrthngtn | The step after that for more inlining is to allow us to inline sp_resumption itself, which I think is really mostly work in the graph merge; the way I wrote the code in the resumption search should already handle multi-level inlines. | 14:07 | |
However, in the inline log I see a huge amount of "a deopt may happen before arguments are processed" | 14:08 | ||
Which I think is our main blocker | |||
And I think that's due to things like hllize sticking in guards in the dispatcher translation that are not require | 14:09 | ||
*required | |||
BUT when I stop inserting those, the NQP build blows up | |||
That will need sorting out before we can really have a chance of inlining as well as before | 14:10 | ||
timo | you gave me the hope of inlining better than before :D but that will come in time of course | 14:14 | |
jnthnwrthngtn | Well, there will be things we can inline now that we couldn't before | 14:16 | |
Actually my test case is of a simple (but not onlystar) proto, where we inline the proto itself | |||
Which was impossible before | |||
Oh finally, I managed to cause a deopt that busts things | |||
timo | de-ooped | 14:17 | |
jnthnwrthngtn | OK, now to recreate dispatch run call records... | 14:19 | |
Hmmm. I wonder if I really should do it that way... | 14:22 | ||
The code would be vastly simpler with a special kind of call stack record for a deopt'd resume init arg set | 14:24 | ||
Hm, or would it | 14:25 | ||
Yup, it's possible to reconstruct a sufficiently convincing run dispatch record, but not pleasant. | 14:35 | ||
Deopt is difficult enough to debug already. | |||
Got it "working" for my example. Turns out somewhere deep in compiling CORE.setting it now segfaults though :/ | 16:01 | ||
Thankfully, it was a silly thinko | 16:13 | ||
Geth | MoarVM/new-disp: 56067a06ad | (Jonathan Worthington)++ | 8 files Allow inlining of dispatches with resume init args This enables inlining optimizations in `sp_runbytecode` when there are `sp_resumption` instructions stacked up before it. (It does not yet allow inlining of `sp_resumption` instructions themselves). The key pieces are: ... (11 more lines) |
16:22 | |
jnthnwrthngtn | That was kinda tricky to work out how to do, but the implementation is relatively straightforward in the end | 16:28 | |
16:30
evalable6 left,
linkable6 left
16:32
evalable6 joined
|
|||
dogbert11 | jnthnwrthngtn++ | 16:38 | |
17:15
brrt left
|
|||
Geth | MoarVM/new-disp: 31d53e35d5 | (Jonathan Worthington)++ | 3 files Enable inlining of sp_resumption By doing all of the required index fixup: * In the sp_resumption op itself * In the inline table * In the spesh resume init table And merging the spesh resume init table itself. |
17:21 | |
lizmat | jnthnwrthngtn: so should that make a performance difference for test-t? | 17:23 | |
or would you like me to find out? :-) | |||
jnthnwrthngtn | We have some newly busted stuff to hunt from this, alas, but that triage would be nice to share. | 17:24 | |
lizmat | ok | 17:25 | |
jnthnwrthngtn | lizmat: Maybe, but so much inlining is being forbidden by "potential deopt before args processing" that I suspect it'll block many of the benefits. | ||
Some improvement in test-t is likely (it'd be interesting to see how much) | 17:26 | ||
Running it with MVM_SPESH_INLINE_LOG=1 and looking for "a deopt may happen before arguments are processed" will give a feel for how much is being left undone because of that issue | 17:27 | ||
Time to cook, rest, etc. bbl | 17:29 | ||
lizmat | It's remarkably quick: | 17:33 | |
$ time raku test-t.pl <hello.csv | |||
Segmentation fault: 11 | |||
[Coke] | Regarding post-deploy merge - I think the windows build issue is a blocker, but the nativecall concurrency issue is probably not (though I think we'll need to track that down over the next month.) I can see if I can duplicate ... was it masterduke? Nine? 's fix for the VLA. | 17:34 | |
(if no one else gets to it.) | |||
Is there a list of issues to fix before the merge / list of expected things to hit before first release? | 17:35 | ||
(afk) | 17:36 | ||
18:03
reportable6 left
|
|||
dogbert11 | MoarVM oops: Failed to find deopt index when processing resume | 18:04 | |
18:05
patrickb joined
|
|||
jnthnwrthngtn | dogbert11: Yeah, spotted that one; it only happens with the JIT enabled | 18:05 | |
lizmat | jnthnwrthngtn: so no test-t numbers | 18:08 | |
dogbert11 | jnthnwrthngtn: aha | ||
18:30
linkable6 joined
|
|||
lizmat | m: sub e() { 42 }; say e | 18:49 | |
camelia | 2.718281828459045 | ||
lizmat | hmmm | ||
19:05
reportable6 joined
19:22
patrickb left
|
|||
timo | yeah cuz e is a term, right? | 19:23 | |
lizmat | yup | 19:24 | |
but I thought locally defined things would have precedence? | |||
or is that because the name of the sub is really &e | 19:25 | ||
and "foo" is just syntactic sugar for "&foo()" ? | |||
timo | probably terms will always have precedence over subs without parens | 19:45 | |
19:51
cognominal left
|
|||
lizmat | I guess :-) | 19:59 | |
it's still a bit of a gotcha | |||
m: sub now() { 42 }; dd now | 20:00 | ||
camelia | 42 | ||
lizmat | he? | ||
I though now was also a term ? | |||
hmmm | |||
m: sub pi() { 42 }; dd pi | 20:03 | ||
camelia | 3.141592653589793e0 | ||
lizmat | hmmm.... | ||
lizmat goes away for a bit for some epibration | |||
nl.wikipedia.org/wiki/Epibreren # for the more Dutch inclined :-) | 20:06 | ||
dogbert11 | jnthnwrthngtn: not the best golf ever but try the code snippet below with MVM_SPESH_NODELAY=1 | 20:26 | |
for ^10 { my $proc = Proc::Async.new($*EXECUTABLE, '-e', '$*OUT.write(Blob.new(65, 66))'); my $result = ''; $proc.stdout.tap({ $result ~= $_ }); await $proc.start; } | |||
japhb | lizmat: That is a truly excellent term. Right up there with 'defenestration' I think. | 20:38 | |
jnthnwrthngtn | dogbert11: Thanks, will look at it tomorrow | 21:24 | |
22:52
linkable6 left,
evalable6 left
22:54
RakuIRCLogger left
22:55
TempIRCLogger left,
evalable6 joined
22:56
linkable6 joined,
Geth left,
lizmat left
23:00
lizmat joined,
TempIRCLogger joined
23:01
Geth joined
|