<wingo>civodul: very neat that you are using fibers in cuirass :) you'll have to let me know your thoughts <civodul>i'm still debugging a few things though :-) <civodul>it's not always easy to find out what your fibers are doing <wingo>initially i had a system where the fibers would all have ids and you could backtrace them <wingo>but that was too much for a lightweight system, and you can build it just as well on top, so i took it out <wingo>anyway it could be useful to make a wrapper for spawn-fiber that adds this kind of functionality <wingo>so you can get global backtraces, figure out who is waiting on what, etc <civodul>also it seems to create a number of pipes proportional to the number of kernel threads, is that correct? <civodul>i saw a lot of open FDs, prolly related to the epoll code <wingo>civodul: yes there are two fds per thread, one for the epoll and one is to wake up the epoll when it's sleeping <civodul>ok, i wonder if this could be an issue on machines with many cores <wingo>no i don't think that should be a huge issue. stock fd limit is around 1024 i think on most distros <wingo>so up to about 64 cores you would have 128 fd's of overhead; not so bad; and if you went higher you'd have to know about the fd limit anyway <wingo>e.g. if you aim to serve 100K concurrent clients, you already have to manually tune a core limit <wingo>the limit when you get to that many cores is guile's gc <wingo>i guess in the cuirass case you might be thinking more about worker jobs, perhaps... dunno <civodul>i don't think FDs are a big concern in practice <civodul>it's just the feeling that the "runtime" in general is using quite a bunch of FDs and threads (GC threads notably) <wingo>yeah we could do better if we instead did gc via safepoints -- i.e. one thread determines that it needs to gc -> set flag indicating all threads should come to a safepoint and help gc; as soon as a thread comes to a safepoint (a handle-interrupts instruction for example) then it should mark itself as in safepoint, mark the values on its stack, wait until all other threads are sleeping, then participate in marking as a mark worker <wingo>an open question would be how to get mark parallelism when your app has only one thread. dunno <wingo>maybe the sleeping gc threads are cheap enough :) <wingo>at least with dedicated mark threads, you can control affinity of those threads <wingo>switching to safepoints would be very good from a complexity-of-gc-implementation point of view, if we switch to having our own gc <wingo>but perhaps a bit of a pain for users who would have to be more assiduous about scm_leave_guile etc <civodul>yeah, embedding in libguile C may become harder i guess <civodul>looks like scheduler-work-pending? doesn't account for fibers that are suspended waiting on an FD event, no? <wingo>if you want run-fibers to go forever you should arrange for that to happen otherwise <wingo>see what (fibers web server) does <manumanumanu>amz3: How do you mean? My problem is that I want to abstract away the user having to handle the pointer to the C struct. One neat way would be using ports, but that way I can't return any data (since close-port returns #t or #f). Using closures is a bit clunky imho, since I have two different operations (update and close) <manumanumanu>I have thought a bit of a functional interface, which works a bit like a curried function, where the C state is copied on each operation. That way, I get continuation safety, at the cost of ~300 bytes per operation. I don't really see the use case for it though, since using multi-shot continuations in software doing encryption/validation seems like a bad idea (TM) <wingo>i have never used multi-shot continuations :P <wingo>never for any real use. i don't think they have one. <manumanumanu>I do 0-100 in about 2 seconds. First I show them call/cc and explain undelimited continuations, and when people ask "what use does this have", I show them some code using fibers :D :D <manumanumanu>"Yes, lowly c++ programmer, this is how we do multi-threading now." <manumanumanu>I am only half joking. I showed a friend of mine recently, and he was blown away by guile. Especially the macros (i showed him my racket-loop macros), the ability to alter a program while running and by fibers. <wingo>once-resumable continuations are useful of course <manumanumanu>wingo: Yeah, and iirc they are easier to make fast than regular call/cc. Chez has one-shot continuations, that are considerably faster than regular call/cc. Not that it matters to guile, since we got the cool stuff :D <wingo>i think what chez considers to be one-shot are escape-only continuations <wingo>no? not suspend/resume things <wingo>guile has that optimization too, but chez can resume faster because it has chained stack segments <manumanumanu>So... I have a macro that automatically converts bytevectors to pointers and #f to %null-pointer for the FFI. I going to polish it a bit, but in my opinion, it greatly simplifies using the FFI. How would I go about maybe having it included in guile? It is a thin wrapper around pointer->procedure that adds the type bytevector and wraps all pointers in a lambda that converts #f to %null-pointers. All inlined by <wingo>send it to the list and see what people say :) <wingo>bytecode depends on word size (32 or 64 bit) and endianness <manumanumanu>wingo: so that means code compiled on my 64bit machine won't work on my 32 bit one? <wingo>correct, but you can cross-compile the .go files <wingo>see the makefiles in prebuilt/ <manumanumanu>wingo: Have I understood this correctly?:I have a foreign-ref procedure that works on non-platform-dependent types, and size_t. For size_t it decides the (sizeof size_t) at compile time, and returns the correct bytevector-ref procedure to read that memory location. In a .go-file that macro would have already been expanded and compiled, and I could potentially send a bytevector-u64-native-ref to a 32bit <manumanumanu>wingo: Oh wait. I can work around it while making the code better :D <wingo>if you want the size_t to apply to the target size_t then you need to (define target-size_t (match (target-word-size) (4 uint32_t) (8 uint64_t))) <amz3>manumanumanu: if you want to do the good thing, you must use disjoint types and not expose the pointer type to the user define-wrapped-pointer-type <amz3>manumanumanu: I don't about the API you must, I am just saying that industria use a (make-hash) procedure that returns a handle over the final hash, and then does a bunch of (hash-update! hash "foo") and then (hash-finish! hash) will return the final bytevector ***javier_ is now known as Javyre
<roelj>Ehm, is there a way to let sxml->xml not escape a character? Like so: (sxml->xml `(div "15 " < " 20")) <roelj>Unfortunately, that doesn't work. <roelj>Ha! It seems that this works in Javascript `("'5' + String.fromCharCode(60) + '10'"). So that's a work-around for my use-case. <jeko>With SRFI-64, the cleanup form is the last expression of the test-group-with-cleanup. Is the set-up form the first expression of the test-group-with-set-up ? ? <jeko>oh I just saw there is no test-group-with-set-up haha x_x