github.com/moarvm/moarvm | IRC logs at colabti.org/irclogger/irclogger_logs/moarvm Set by AlexDaniel on 12 June 2018. |
|||
00:03
sena_kun joined
00:05
Altai-man_ left
02:02
Altai-man_ joined
02:05
sena_kun left
02:32
lizmat joined
|
|||
timotimo | apparently using a react/whenever on a process when tapping the stdout will not do backpressure on the process itself | 02:52 | |
i tried with a "sleep" in the "whenever $process.stdout" block, but the memory growth was many times as much as the amount of characters it said it "got" | |||
sleep 2, to be exact | 02:53 | ||
not infinite sleep | |||
i thought we had this whole "permit" system for i/o that does backpressure on this level? | |||
hum, so the default permit value is -1, unless you call nqp::permit on the AsyncTask? | 03:05 | ||
looks kind of like the only usages of permit are with -1 on the third argument, i.e. turn something on at full blast (this is searching for nqp..permit in all of rakudo) | 03:09 | ||
oh, if i use permit with a number i'll have to permit it again manually so that stuff continues happening after the initial permit amount is drained? i guess that makes more sense than just renewing the permit when it's somehow magically determined that a work item has been processed | 03:20 | ||
have i been looking at a far outdated generated core setting? | 03:40 | ||
perhaps not too outdated | 03:41 | ||
04:03
sena_kun joined
04:05
Altai-man_ left
|
|||
timotimo | i'm now "shit posting" a patched rakudo that permits the process to write 128 times every 1 second to see if that works well enough to keep memory usage low in this workload | 04:14 | |
ideally it'd start with a lot and go down to a little, so that it can spawn its maximum threads early and then have a constant trickle of chunks for new threads to be started with | 04:15 | ||
i can literally implement that lol | 04:17 | ||
06:02
Altai-man_ joined
06:05
sena_kun left
07:34
tobs joined
07:43
zakharyas joined
|
|||
nwc10 | good *, #moarvm | 07:47 | |
I am temporarily in a deeper (longer) hole than usual | |||
08:03
sena_kun joined
08:05
Altai-man_ left
09:22
squashable6 left
09:24
squashable6 joined
|
|||
jnthn | nwc10: Gotthard base tunnel? | 09:59 | |
10:02
Altai-man_ joined
|
|||
lizmat | jnthn: github.com/rakudo/rakudo/blob/mast...rs.pm6#L92 | 10:03 | |
*every* time something does "but True", it will run this code and create a new type | |||
every single time | 10:04 | ||
a new type | |||
that can't be right ? | |||
10:05
sena_kun left
|
|||
jnthn | lizmat: That's how it reads to me. | 10:10 | |
lizmat: There's surely a more optimal way to do that :) | |||
lizmat | yeah | ||
I was thinking of making trying to but an non-value type fatal | 10:11 | ||
and cache the roles on the .WHICH of the value | |||
jnthn | I think this code has been around for a long while, and maybe predates 6pe (6model parametric extensions), which provides a mechanism for caching these things. | ||
No, don't build your own cache. | |||
Because it will probably get precomp wrong | 10:12 | ||
(6pe knows how to intern them across compilation units) | |||
I'm not sure that we should cache it on value though | 10:13 | ||
Well, actually, for enum types that makes sense | |||
For for Int, there are a lot of integers ;) | |||
lizmat | well, it closes over the value given | ||
jnthn | I think maybe the best way to do it is that the role brings in an attribute to hold the value | 10:14 | |
lizmat | well, creating a new type every time, is not only memory hungry, it also eats CPU like crazy | ||
jnthn | And then we create one role per type that is mixed in | ||
lizmat | loop { my $a; $a but True } eats about 20MB / sec on my mechine | ||
jnthn | one for Bool, one for Int, etc. | ||
lizmat | I hear what you're saying, yet I have no clue on how to move forward on this :-( | 10:20 | |
jnthn | Look at how the mixin cache works. You need | 10:24 | |
1. some type to serve as the "base" for the caching | |||
2. to have a parameterizer that builds the role based on the type (I think the simplest way is to have an attribute with the name of the type) | 10:25 | ||
3. Then use the (iirc) parameterizetype op to obtain the produced role for the type (which will use a cached one if possible) | 10:26 | ||
4. Mix that role in, and you can probably use the whole BUILD_LEAST_DERIVED thingy to set the attribute | |||
lizmat | ok, let me try to grok that | 10:27 | |
10:50
patrickb joined
11:28
zakharyas left
11:45
AlexDaniel joined,
AlexDaniel left,
AlexDaniel joined
12:03
sena_kun joined
12:05
Altai-man_ left
12:57
MasterDuke left
13:08
MasterDuke joined
13:34
zakharyas joined
|
|||
timotimo | media.ccc.de/v/ASG2019-127-gnu-pok...inary-data | 13:37 | |
"GNU poke is a new interactive editor for binary data. Not limited to editing basic entities such as bits and bytes, it provides a full-fledged procedural, interactive programming language designed to describe data structures and to operate on them. Once a user has defined a structure for binary data (usually matching some file format) she can search, inspect, create, shuffle and modify abstract | |||
entities such as ELF relocations, MP3 tags, DWARF expressions, partition table entries, and so on, with primitives resembling simple editing of bits and bytes. The program comes with a library of already written descriptions (or "pickles" in poke parlance) for many binary formats." | |||
13:55
Kaiepi left
|
|||
[Coke] | ... wow, I haven't heard "pickle" since the late 90s when I was writing code in Modula-3. | 13:55 | |
13:56
Kaiepi joined
|
|||
timotimo | well, python has pickle | 13:58 | |
14:02
Altai-man_ joined
14:04
sena_kun left
|
|||
[Coke] | as you now know, I am not a python guy. :) | 14:08 | |
timotimo | :) | 14:09 | |
why can't we unpickle python-pickled data into raku datastructures yet | |||
including code because i have no other hobbies | 14:10 | ||
nwc10 | jnthn: no, merely the Lainzer Tunnel) | 14:25 | |
but the train wifi worked way better than I assumed | |||
[Coke] | nwc10: heh. whenever I used to take the train from Albany to NYC, I would have to bring a book the wifi (and cell coverage) was so bad. | 14:27 | |
... fixed by just never leaving the house these days. :| | |||
nwc10 | aargh, this is a new one on me - this train would fail the slop test | 14:32 | |
(ie does it spill your cup of tea) | |||
it is vibrating the table | |||
(this is not jolts caused by poor track, which is the usual intent of the "slop test" joke. But also about the laziest way to inspect the track) | 14:33 | ||
jnthn | Hm, what's the source of the vibration? | 14:34 | |
nwc10 | I suspect that something has chanced on the resonant frequency of the seat assembly | 14:35 | |
from master/master/master, is this an error I'd currently expect to see from Rakudo: New type Perl6::Metamodel::CurriedRoleHOW for Perl6::Metamodel::ConcreteRoleHOW is not a mixin type | 14:36 | ||
ie have I messed up my build trees, or is it a temporary LTA upstream ? | |||
14:50
patrickb left
14:51
patrickb joined
|
|||
nwc10 | what is this heresy? Surely emacs is sufficient to edit *anything*? :-) | 14:58 | |
jnthn | nwc10: Where do you see it? It's not familiar, but I'm a bit back from HEAD thanks to being in branches nearly all the time these days... | 15:00 | |
nwc10 | jnthn: I think that I might have goofed the NQP build (ie the wrong build tree, or just the wrong install target) | 15:01 | |
15:14
patrickb left
15:38
MasterDuke left
15:59
MasterDuke joined
16:03
sena_kun joined
16:04
Altai-man_ left
16:13
Kaiepi left
16:14
Kaiepi joined
18:02
Altai-man_ joined
18:04
zakharyas left
18:05
sena_kun left
18:34
Kaiepi left,
Kaiepi joined
18:45
squashable6 left
18:49
squashable6 joined
18:56
[Coke] left
|
|||
nwc10 | jnthn: I think that this is likely to trigger a discussion that will have to happen on another day. | 19:07 | |
What I know (from adding a whole lot of assertions, etc) is that this code: | |||
./rakudo-m | |||
-Ilib -e 'my $m = Mix.new-from-pairs("a" => -20, "b" => 1.5); my $a = $m.Bag; my $b = $m.BagHash' | |||
(which is part of t/spec/S02-types/mix.t | |||
Is performing a hash delete while an iteration is in progress | 19:08 | ||
and, is there a Raku language level spec on whether this is allowed, and hence needs to be supported? | |||
it *happens* to work currently | |||
but is it supposed to? | |||
no, I shall be more eaxcting | 19:09 | ||
it happens to work currently on MoarVM | |||
I have no idea about other backends | |||
as to the other thing I was confused about - problem was me. One build tree (NQP I think) was not at the master I thought that it was | 19:10 | ||
MasterDuke | what is it deleting? | 19:15 | |
nwc10 | "a" => -20 I guess | ||
and I must be tired | |||
I have a backtrace from oops | |||
at SETTING::src/core.c/Mixy.pm6:119 (/home/ghdev/Perl/rakudo4/blib/CORE.c.setting.moarvm:BAGGIFY) | 19:16 | ||
also whether it hit oops or not depends on hash randomisation | |||
MasterDuke | doh | ||
nwc10 | you're going to need to make a few more d'ohs before you catch up with me :-) | 19:17 | |
or is that :-( | |||
jnthn: OK, now I've realised my d'oh | |||
and read the code | |||
it's doing exactly the Perl 5 permitted operation - deleting the key at the iterator | 19:18 | ||
(and then advancing the iterator) | |||
so, um, er, erk. ish | 19:19 | ||
the *exact* operation is probably viable, if it's done as a "method" on the iterator, not the hash | 19:20 | ||
but I have no idea if Java, JS or anything else "we" (er, or them, over there on #raku) would like to target can support this | 19:22 | ||
looking that code in Mixy.pm6, I think that it could be re-written to stack up the deletes in an array, and then loop over the array to perform them, only after the entire hash has been iterated over | 19:23 | ||
set_difference.pm6 is doing the same (dangerous) pattern "at" line 122 | 19:25 | ||
and SETTING::src/core.c/Rakudo/QuantHash.pm6:952 | 19:27 | ||
lizmat | nwc10: sure it can | 19:28 | |
I wrote it the way it is now *because* I checked with jnthn at the time, to know for sure it is ok to delete the key currently at the iterator | |||
nwc10 | OK. That is an implementation detail | 19:29 | |
lizmat | should we decide that is no longer a good thing, then I'll rewrite the code accordingly | ||
nwc10 | that is an implementation detail that I wasn't aware of as being needed | ||
and | |||
lizmat | if we can make hashes faster by *not* allowing that | ||
nwc10 | well, actually | ||
lizmat | by all means... go for it, I'll make the necessary changes | ||
nwc10 | I tweaked the implenmentation such that it can do *exactly* this delete without problems | ||
but my (sort of problem) is that I can't validate that this is what is happening | 19:30 | ||
lizmat | ? | ||
nwc10 | and every other sort of delete is "potentially dangerous" (I think that currently my new code could oops) | ||
acutally, with the current MoarVM master | |||
any other delete, at the same time as an iterator exists | |||
could lead to a "read from freed memory" | 19:31 | ||
I might need to think about this - I've made plenty of mistakes already today - that "it could do X" might be another | 19:32 | ||
19:32
SmokeMachine joined
|
|||
lizmat | nwc10: you mean in a single thread ? | 19:33 | |
or multi-threaded ? | |||
nwc10 | in a single thread | ||
19:33
kawaii joined
|
|||
nwc10 | if the high level code happens to have two different iterators on the same hash | 19:33 | |
lizmat | am pretty sure that would not happen in a single thread, unless people started doing their own nqp::iterator() calls | 19:35 | |
from a HLL point of view | |||
nwc10 | OK | ||
I don't actually know the HLL stuff here :-) | |||
I'm starting at the bottom | |||
lizmat | well... the iterator gets wrapped in a Seq | ||
nwc10 | but MVMIter holds a pointer | ||
oops | |||
MVMIter as implemented currently holds pointers direct to C memory "owned" by the hash | 19:36 | ||
lizmat | so technically, you *could* do something like %hash.grep: { %hash.keys } | ||
nwc10 | and if there are two iterators, and a hash access to a key found via the first (or anything else) causes the hash to change | ||
then the second MVMIter could be left with a pointer to freed memory | 19:37 | ||
lizmat | or worse: %hash.grep: { %hash<foo>:delete } | ||
so, even if the core would ensure only a single iterator / hash at a time, HLL user code *could* circumvent that | 19:38 | ||
perhaps make it fatal to have 2 iterators on a hash at the same time ? | 19:39 | ||
nwc10 | that sounds awkward, and that really isn't the danger here. | ||
it's sort of | |||
1) we can cope with deleting the key that any (or all) iterators are currently pointing to | |||
but | |||
2) we can't "cope" with deleting any other key - ie | |||
right now we could SEGV or worse | 19:40 | ||
the code I've written would oops | |||
and whilst I could make it not oops | |||
that might hide other bugs - the oops was supposed to be the "how on Earth did you even get here - is MoarVM buggy?" | |||
and | |||
3) We don't have a way of finding the active iterators belonging to a hash | 19:41 | ||
meaning that | |||
4) I can't see a way of "enforcing" sanity - where sanity is "deletes are fine on hashes while iterators exist, providing either you only delete at the current iterator position, or you never read again from the iterator once the delete happened" | |||
I think | |||
the NQP code as written in the setting actually works just fine with the current implementation | 19:42 | ||
and my new hash (as of two days ago) | |||
but I don't know how to spot the "OK" case | |||
lizmat | as in: ok to delete the current ? | 19:43 | |
nwc10 | yes. it is OK to delete the current | ||
(Perl 5 neesd this, and I figured out how to make that work, by reversing the order that the internal hash metadata is traversed) | |||
but I don't know how to fix my "paranoia" test code to be happy with this delete | 19:44 | ||
lizmat | would it make sense to have an iterator walk all of the hash and create a fixed list ? | ||
nwc10 | I think "no" because that would be expensive on memory | ||
a slightly cheaper option is a way to be able to actually track active iterators | 19:45 | ||
circular linked list of them | |||
but this would then need a C API for "I'm releasing this iterator" and some code added to MoarVM | |||
lizmat | why not set a flag on the hash if there is an iterator active, and as soon as it has produce the final value, reser it? | 19:46 | |
nwc10 | that was the point 3 above - We don't have a way of finding the active iterators belonging to a hash | ||
lizmat | with an option to resetting the flag and disabling the iterator | ||
nwc10 | I don't think that that solves this one, and I'd sort of implemented that already in my branch by having the iterators go in reverse, so that the end index is 0 | 19:47 | |
as in zero | |||
not "current size of hash" | |||
lizmat | if there would be only one active iterator allowed, then you wouldn't need to keep track of which iterators are active on a hash? | ||
nwc10 | because zero is the same everywhere :-) | ||
lizmat | hmmm | ||
nwc10 | "only one active iterator allowed" - welcome to Perl 5 | ||
and this is seen as a deficiency | |||
lizmat | well, maybe there is a reason for that :-) | ||
maybe we should try to get some inspiration on recent hashing research ? | 19:49 | ||
jnthn | The other thing to keep in mind is that it's legal for multiple threads to iterate the same hash (so long as they don't modify it, of course) | 19:51 | |
So any "know the iterators" scheme would entail locking, and cost | |||
Well, the cost of the locking | |||
nwc10 | All the stuff I've found so far as been about hash tables and how to implement them, has been about insert, delete, and fetch (on elements that are there, and elements that are missing) | ||
not iterators | |||
jnthn: gah yes. | |||
currently I'm just wondering about removing my paranoia check for "at end" | 19:52 | ||
having validated that all the places that hit it are actually "safe" because they delete at the current iterator | |||
19:52
tbrowder joined
|
|||
nwc10 | and I made that work | 19:52 | |
lizmat | but we're still not safe with an iterator in another thread when changes are made to the hash, right ? | 19:53 | |
nwc10 | correct | ||
and I think that we're not safe with an iterator in the same thread, and changes are made to the hash | 19:54 | ||
(both current implementaion, and my proposed new one) | |||
lizmat | but the new one needs a lot less memory and is faster ? | 19:55 | |
nwc10 | er, I've not yet got to the "faster" bit. I was trying to make it work at all first | ||
lizmat | Ah, I see | ||
nwc10 | it should be using less memory | ||
lizmat | but that's the goal, is it not ? | ||
nwc10 | I admit | ||
if it's not measurably faster, I will be disappointed | |||
lizmat | been there, I hope you will not be disappointed | 19:56 | |
actually, at this point in time, I'm not sure what I'd want more: safe hashes that will never SEGV when being changed from different threads | 20:02 | ||
20:03
sena_kun joined
20:04
Altai-man_ left
|
|||
nwc10 | OK, because I am thoroughly paranoid, and investigated all 15 failures... | 20:07 | |
I find that this one: | |||
./rakudo-m -Ilib -e 'my %h; my $i = 0; for "a".."z" { %h{$_} = ++$i; }; my @all = %h{ %h.keys }; %h{*}:delete; ' | 20:08 | ||
is a problem (ish) | |||
at the C level it's calling "next" when the hash has been modified somehow | |||
I need to dig further on this one | 20:09 | ||
jnthn | Hm, why is that one a problem? The assignment into @all is eager... | ||
nwc10 | but it doesn't seem to be "deleting at the current iterator position" | ||
I don't know why it's a problem | |||
I'm tired - it seems that today's travelling took more out of me that I expected | |||
jnthn | OK, it just feels like a "nothing should be awkward here" | 20:10 | |
(Unless there's something else surprising going on.) | |||
nwc10 | Unlike Perl 5, I have no feel for "how does the language map down to API calls" | ||
I have no idea. Figuring out the "surprising" I think is left as a task for another day | |||
which won't be tomorrow | |||
jnthn | Ohhh...maybe actually it golfs down to just the %h{*}:delete | ||
nwc10 | (unless plans chance) | ||
change | |||
jnthn | Which I guess maybe does iterate all of the keys and delete them, if it's naively implemented | 20:11 | |
nwc10 | I can't answer that | ||
it has to be differnt in some way, as it's hitting my paranioa oops in MVM_str_hash_next | 20:12 | ||
(which is what replaces HASH_ITER_NEXT_ITEM) | |||
so it will be the case MVM_ITER_MODE_HASH in shift in MVMIter.c | 20:13 | ||
(let's go check that) | |||
yes, location equivalent to the current line 111 of MVMIter.c | 20:15 | ||
and the Internet confirms my recolection that 111 is considered to be unlucky, but in far more detail than I ever thought possible: en.wikipedia.org/wiki/Nelson_(cricket) | 20:17 | ||
lizmat | nwc10: and this is from %h{*}:delete ? | ||
nwc10 | yes. My `say "yes"`; got called | 20:18 | |
no, I don't know why | |||
but something about `%h{*}:delete` is implemented in a way that ends up calling C APIs in orders that are (I guess) LTA | 20:19 | ||
lizmat | nwc10: let me get back to that one, ok | ||
nwc10 | but I think that I should stop digging and go to bed | ||
lizmat | What I see, is this: | 20:20 | |
multi sub postcircumfix:<{ }>(\SELF, Whatever, Bool() :$delete!, *%other) is raw { | |||
SLICE_MORE_HASH( SELF, SELF.keys.list, 'delete', $delete, %other ); | |||
} | |||
which tells me it is passing a list of keys to be deleted | |||
jnthn | Looks like, yes | 20:21 | |
Probably not a terribly common construct to rush to optimize, but almost certainly there's a win to be had there | 20:22 | ||
lizmat | $more.cache.flatmap( { SELF.DELETE-KEY($_) } ).eager.list; | ||
nwc10 | jnthn: I think that I need to "temporarily" go "AFK" (ie sleep) | 20:23 | |
lizmat | nwc10:: good night, sleep well! | ||
jnthn | nwc10: Rest well | 20:24 | |
nwc10 | but in the future I need to go digging here - what is that Raku code turning into, and why is it calling MoarVM APIs in a strange order that doesn't seem to reflect what it ought to be doing (even if it could be written better) | ||
and thanks both of you (and MasterDuke) for being awake with feedback at a useful time | 20:25 | ||
lizmat | nwc10: perhaps an API for resetting the hash, aka setelems(0), would be useful | ||
the big issue with deleting all keys from a hash, is that the values should be returned as well | 20:26 | ||
and that currently requires an atkey | |||
if a deletekey would also return its value, then the HLL code could be much simplified | |||
and return nqp::null if it doesn't exist, like with atkey | 20:27 | ||
20:28
chansen_ joined
|
|||
jnthn | lizmat: Ah, right, we discussed that part, but never quite got around to it. :) | 20:29 | |
20:57
squashable6 left,
squashable6 joined
21:35
kawaii left
21:36
kawaii joined
21:38
AlexDaniel left
22:02
Altai-man_ joined
22:05
sena_kun left
22:48
leont left
|
|||
lizmat | just ran a profile with %h{*}:delete, and only 6% of CPU was spent actually deleting the keys, and about 80% in generating the return values | 22:52 | |
which, in my benchmark, were just thrown away | |||
23:01
lizmat left
|
|||
timotimo | send spesh logs :) | 23:02 | |
23:04
lizmat joined
23:55
squashable6 left
23:57
squashable6 joined
|