IRC channel logs

2021-05-06.log

back to list of logs

<flatwhatson>sneek: later ask ludovic any chance you were seeing SIGABRT with "mmap(PROT_NONE) failed", not just warnings? that would be the same out-of-memory bug. i guess some guix infrastructure could legitimately hit this case due to memory pressure while running builds
<sneek>Got it.
<civodul>flatwhatson: oh right, it may have been SIGABRT actually
<civodul>like this one: https://issues.guix.gnu.org/40525
<civodul>looking at https://issues.guix.gnu.org/40525#4 there could be a bug still lingering here
<flatwhatson>oh yep, that's exactly the bug. well, i have a patch for libgc 8.0.4: https://paste.gnome.org/pvaze9jpz
<civodul>looks like a workaround more than a fix though, no?
<flatwhatson>not really, mprotect(PROT_NONE) is as well documented as mmap(PROT_NONE). it's not clear why libgc would prefer mmap as the common case
<flatwhatson>latest master libgc actually expands that ifdef to cover AIX, HPUX and HAIKU which exhibit the same/similar problem
<lampilelo>i git-bisected guile and it seems that the incompatibility between geiser and guile started when (read) was replaced by (read-syntax) in language/scheme/spec.scm, i know too little about how stuff works internally to really understand the problem
<lampilelo>i assume the tests for repl are enabled and pass (otherwise someone would notice), is there something different between the test cases and geiser<->repl connection? it's faulty for both tcp and unix sockets
<lampilelo>maybe tests use the same stuff in both client and server, but the incompatibility lies in a changed spec?
<lampilelo>when talking with outside world, that is
<lampilelo>ok, i'm leaving it at that for now, just wanted to dump what i learned, maybe someone would know what's the matter, the breakage starts at commit is 03448b289d9804bb27b633b82e22cf7be55743c5
<lampilelo>s/is//
<flatwhatson>geiser-guile has some magic around compilation & evaluation, problem is probably in here: https://gitlab.com/emacs-geiser/guile/-/blob/master/src/geiser/evaluation.scm
<lampilelo>so you say it's geiser that should adapt to the new way of doing things? i can add a ticket to their issue tracker tomorrow
<flatwhatson>hard to say who is at fault, but i would start looking there for the root cause of the bug
<lampilelo>geiser's code didn't change though
<lampilelo>ok, i'm going to bed, good night
<flatwhatson>libgc failures now reported upstream: https://github.com/ivmai/bdwgc/issues/353
<daviid>lampilelo: you might wana talk about the geiser problem on #geiser, the author is jao, very nice and very responsive ...
<manumanumanu>rlb: I am not involved in any internal things, but I am playing a lot with data structures at the moment. I don't really see the need for expandable strings, at least not if it makes _every other operation_ more expensive. Representing strings as vectors of N-char bytevector chunks is probably a pretty nice compromise, though. If you allow for an offset you get shared substrings, decent random
<manumanumanu>access, and quick iteration with string cursors. as andy said: mutable strings in scheme is probably a bug in the spec :)
<manumanumanu>It is pretty compact as well: say you make each chunk 32 chars long, meaning each chunk is anywhere between 32 and (worst case) 128 bytes. One pointer per chunk. I don't know enough about the guile internals, but it sure is more compact than a vector of chars.
***zap1 is now known as zzappie
<dsmith-work>{appropriate time} Greetings, Guilers
<mwette>Guile != Scheme; see https://opensource.com/article/21/5/learn-lisp
<rlb>manumanumanu: right - it's certainly feasible. A plain utf-8 implementation has potentially better locality, and much better external compatibility (e.g. say we wanted to use libpcre). It might also have a performance advantage if there are cases where we can use more existing, heavily optimized code. But of course the persistent version you describe has other advantages (space in cases where the sharing works well, etc.).
<rlb>What got me thinking about it again lately, fwiw, was implementing clj's #"foo" regex support via libpcre. That's much more expensive right now because libpcre just doesn't support latin-1. But for that to be optimally efficient for guile extensions that only rely on the public api, we'd also have to support some way to use the internal utf-8 pointer (even if we never *promised* that it wouldn't be a copy).
<mwette>rlb, manumanumanu: you might be interested in vlists described in the manuall, as well as intsets and intmaps under (language cps)
<wingo>moo
<sneek>oom
<lampilelo>wingo: u broke geiser with this https://git.savannah.gnu.org/cgit/guile.git/commit/?id=03448b289d9804bb27b633b82e22cf7be55743c5 it seems
<wingo>how? :)
<leoprikler>probably because geiser doesn't understand read-syntax
<lampilelo>since read was switched to read-syntax in this commit, it feels like this is the only explanation
<wingo>but geiser doesn't call read-syntax
<wingo>does geiser call (language-reader (lookup-language 'scheme)) or something like that?
<lampilelo>doesn't call read either, i don't really know what's going on here
<dsmith-work>But that is where git-bisect landed?
<lampilelo>yes
<wingo>my guess is that geiser detects the current language and for some reason uses the current language's reader but also parses that read data for some reason
<wingo>which... the simple solution is that if the result of calling the current language's reader is a syntax object, to do syntax->datum on it. not so great for debugging info tho
<lampilelo>wingo: there's no lookup-language or language-reader anywhere in geiser's and geiser-guile's codebases
<wingo>i would think that geiser should rather do something more intelligent so as to preserve source locations for bare symbols, numbers, etc
<wingo>good luck debugging it, hope these pointers help :)
<daviid>it definitely parses the results, because, as an example, it would display guile-cv images (if proper setting to do so), not just return the result ...
<daviid>*geiser definitely parses the results ...
<lampilelo><flatwhatson> geiser-guile has some magic around compilation & evaluation,
<lampilelo> problem is probably in here:
<lampilelo> https://gitlab.com/emacs-geiser/guile/-/blob/master/src/geiser/evaluation.scm
<lampilelo>i wish i knew more about the codebases, now i'm just passing the info around
<lampilelo>i told geiser's maintainer about the problem and put a ticket on their issue tracker
<lampilelo>so from what you're saying it's just solely geiser's problem
<wingo>well. i mean evidently something changed in guile from an interface pov. it's not the existence of read-syntax
<wingo>but rather that one part of the compiler calls it
<wingo>am a bit perplexed as to how that could break geiser's behavior
<wingo>if you could get a backtrace of the error that would be helpful :)
<dsmith-work>lampilelo: Is that broken with 3.0.6 or with master? (there have been several fixes in master since 3.0.6)
<lampilelo>i think i checked it with master too and it didn't work either, but i'm going to confirm
<lampilelo>wingo: and there's no backtrace because nothing really produces an error, it looks like geiser interprets what guile sent to it wrong
<lampilelo>returns garbage, but doesn't throw
<lampilelo> https://gitlab.com/emacs-geiser/guile/-/issues/9
<wingo>hummmmmmmmmm
<wingo>you know, i bet i know what it is
<wingo> https://gitlab.com/emacs-geiser/guile/-/blob/master/src/geiser/emacs.scm#L35
<wingo>there is some wizardry here to get the repl to read an expression in the current language and pass it as a datum to the repl command
<wingo>which, prolly it is not expecting a syntax object. humm
<lampilelo>i should've invited geiser's maintainer to #guile for this conversation
<dsmith-work>jao is/was usually here.
<dsmith-work>sneek: seen jao?
<sneek>jao?, pretty sure was seen in #guile 11 months ago, saying: i think geiser doesn't work with declarative modules. civodul was telling me the other day. aren't they a 3.x thing?.
<dsmith-work>sneek: botsnak
<dsmith-work>sneek: botsnack
<sneek>:)
<dsmith-work>Picky about them snacks
<civodul>Guix has a package cache: it's a .go file that evaluates to a big list, one item per package, where each item is a vector (with package name, version, etc.)
<civodul>generating this .go file has become CPU-intensive lately
<civodul>and it seems to be a case where we spend time doing bignum operations
<wingo>in slot allocation i guess?
<civodul>incidentally, Guix now has 17K packages, which i can't help but think is right above 16,384 :-)
<civodul>wingo: in truncate-bits
<civodul>called from the assembler
<wingo>funny :)
<civodul> https://web.fdn.fr/~lcourtes/pastebin/generate-package-cache-profile.html
<wingo>hilarious
<civodul>heh, we're pushing it to the limits!
<wingo>well. i mean it is perplexing in many ways
<wingo>but the easy solution is to just dispatch for 16, 32, and 64 bits, signed or unsigned
<wingo>to (<= 0 x #xffff) etc
<civodul>yes, that would avoid the expensive 'ash' and achieve the same i guess
<wingo>not sure if that's the expensive bit
<wingo>bc it's just ashing 1 by 16, 32, or 64, which is not enormous, but maybe that's enough
<wingo>like even the logand could be expensive, internally
<civodul>(1- (ash 1 64)) allocates a couple bignums
<civodul>yeah
<civodul>profile on 1.2.0, which had 15K packages: https://web.fdn.fr/~lcourtes/pastebin/generate-package-cache-profile-1.2.0.html
<civodul>veeerry different!
<civodul>fun
<civodul>x6
<wingo>civodul: pushed a little patch
<wingo>so we should drop a 3.0.7 now, right?
<wingo>given the little bugs in 3.0.6
<civodul>wingo: yes, sounds good!
<civodul>lemme see the patch
<civodul>wingo: ah clever, so it's all peval'd, right?
<wingo>yeah
<wingo>had to use define-syntax-rule to force inlining of the helper, but yeah
<civodul>cool
<civodul>i'll try to see how it performs
<wingo>yay
<civodul>i don't have a reduced test case so i'll disentangle the Guix bits
<wingo>so... what is our perspective on PROT_WRITE | PROT_EXEC
<wingo>we could be more rigorous in the JIT in that regard. would either waste memory or leave WRITE|EXEC half-filled pages
<wingo>or thrash about with mprotect
<wingo>on each jitted function
<civodul>wingo: verdict: 12s instead of 100s wall-clock \o/
<civodul>thanks!
<wingo>what a hilarious fix
<civodul>yeah, those bignums can really hit harder than we might think
<wingo>i hate that :)
<civodul>yeah it's not intuitive!
<civodul>and we've learned & claimed that multiprecision is the one true way to do arithmetic without fear
<wingo>what if it's just our implementation?
<manumanumanu>This has been a funny discussion to follow.
<wingo>i mean would it change with mpn?
<civodul>it could be slightly less stressful for the GC
<wingo>in this concrete case i think specializing on the bit width makes sense fwiw
<civodul>yes
<civodul>regardless of the implementation, (1- (ash x 64)) is going to allocate
<civodul>and we're not wired to pay attention to that i think
<wingo>and there are only three afaics, we should have truncate-s16, truncate-u64, etc
<civodul>yeah
<civodul>with the compiler's help, we could make things like (1- (ash x 64)) allocate only one bignum and then operate in place maybe?
*wingo was wondering about jit protections as apparently apple silicon requires flipping page protections on each jit write
<civodul>ah yes
<civodul>so currently JIT pages remain writable?
<wingo>civodul: (1- (ash x 64)) is already optimized if the 64 is visible to the compiler fwiw. but yeah
<wingo>civodul: right now it's the wild west
<wingo>writable + executable, saddle up
<civodul>uh
<civodul>making them read-only sounds reasonable to me
<civodul>but i don't know what this entails in the code
<wingo>the issue is that the unit of jit compilation is typically smaller than the page size
<wingo>you wouldn't want a page per jitted function...
<wingo>anyway, somethign to think about
<civodul>oh, got it
<civodul>you could flip permissions each time you need to JIT, but it might be expensive
<apteryx>hello! Is there a way to specify 'zero or one' instead of 'zero or more' or 'one or more' when using (ice-9 match) ?
<apteryx>for a the last element in a list pattern
<leoprikler>apteryx (or () (x))?
<civodul>such patterns are not great because they lead to one code path where 'x' is bound and another where it's unbound
<leoprikler>right so you'd have (or (? null? x) (x))
<leoprikler>or you could do it with two different patterns or use a submatch
<leoprikler>or call it (and (or () (x)) y), then y captures the match IIUC
<civodul>i'd use two different patterns
<apteryx>civodul: my gripe with the multiple pattern approach is that it leads to code duplication, no?
<apteryx>leoprikler: thanks for sharing
<leoprikler>you could factor that out into some lambda and then just call it twice
<civodul>apteryx: it depends, it could be that the two clauses have little in common or that there's another way to factorize common code
<apteryx>OK, I'll try something, thank you!
<lampilelo>lol there is a package with elisp bindings to zmq
<lampilelo>exactly 1 package on mepla uses it
<lampilelo>ah, wrong channel ;)