ChanServ changed the topic of #picolisp to: PicoLisp language | Channel Log: https://irclog.whitequark.org/picolisp/ | Check also http://www.picolisp.com for more information
orivej has joined #picolisp
wineroots has quit [Remote host closed the connection]
rob_w has joined #picolisp
<Regenaxer> Uh, embarrassing!!
<Regenaxer> 'int' is *always* 32 bits! 4 bytes!
<Regenaxer> How could I forget this?
<beneroth> it can be smaller, afaik
<beneroth> I believe the C standard gives minimum sizes, but no maximum sizes
<beneroth> or are you talking specifically about LLVM int type?
<beneroth> (if that exists)
<Regenaxer> Here I mean Unix in general
<Regenaxer> Compiler independent
<Regenaxer> On 16 bit machines back then (DOS), integers were 16 bit, yes
<Regenaxer> But on all later systems int was 32 bits
<Regenaxer> I knew this very well
<Regenaxer> I just did not think about it, and especially did not pay attention to the fact that poll() takes an int for the timeout
<Regenaxer> So pil's limit for timers will be 24.85 days in general
<Regenaxer> Any value above I'll convert to -1 (infinite wait)
<Regenaxer> Needs to be documented
<Regenaxer> or, I could change waitFd() to multiple sleeps of 24.85 days ...
<Regenaxer> Will take a walk now and think about it
<beneroth> right
<Regenaxer> or I use ppoll()
<Regenaxer> will investigate later
<Regenaxer> but 24 days should be enough too
rob_w has quit [Quit: Leaving]
wineroots has joined #picolisp
<Regenaxer> ☺ Released a version with ppoll() on Linux and poll() with infinite wait after 24 days on non-Linux
<Regenaxer> I think this is a good solution
<tankf33der> Works here
<Regenaxer> Cool, thanks!
<Regenaxer> Very fast :)
<Regenaxer> I put an "#ifdef __linux__"
<Regenaxer> Is that portable?
<Regenaxer> or, is it defined in Linux everywhere?
<Regenaxer> I must veryfy somehow on Android first
<Regenaxer> ah, no!
<Regenaxer> I tested first on Termux, and this *is* Android :)
<Regenaxer> I use exactly this bin/picolisp in PilBox too
<tankf33der> __linux__ is ok, imho
<Regenaxer> good
<Regenaxer> So on Mac the 'native' problem remains
<Regenaxer> What exactly goes wrong?
<Regenaxer> tankf33der, another issue: Do you use the return value of (stack) in any of your tests?
<Regenaxer> It changed yesterday
<Regenaxer> I added a *really* cool feature: It shows how much stack space each coroutine actually used
<tankf33der> I never used stack function before
<Regenaxer> ok, good then
<Regenaxer> no change in tests needed
<Regenaxer> ((dec . 19) (inc . 19) (T . 75) . 20)
<Regenaxer> gives the unused stack spaces
<Regenaxer> e.g. 19 from a size of 20
<Regenaxer> So we can optimize stack space if there are very many coroutines
<beneroth> cool
<Regenaxer> yeah, interesting
<beneroth> will be useful
<Regenaxer> Seeing which variations consume stack
<beneroth> not using coroutines much yet, but I've got ideas
<beneroth> T
<Regenaxer> For example, a very simple co takes just one kB, but if I set a '!' breakpoint it immediately adds 5 kB
<Regenaxer> Not sure atm where that comes from
<Regenaxer> somewhere in the sub-repl
<Regenaxer> $: (stack)
<Regenaxer> -> ((inc . 63) (T . 250) . 64)
<Regenaxer> $: (co 'nop (loop (yield)))
<Regenaxer> -> NIL
<Regenaxer> : (stack)
<Regenaxer> -> ((nop . 63) (inc . 63) (T . 250) . 64)
<Regenaxer> : (co 'nop)
<Regenaxer> -> nop
<Regenaxer> : (co 'nop (loop (! yield)))
<Regenaxer> (yield)
<Regenaxer> ! (stack)
<Regenaxer> -> ((nop . 58) (inc . 63) (T . 250) . 64)
<beneroth> interesting
<Regenaxer> These stack measurement have a cost though
<Regenaxer> But only once, when a coroutine starts
<Regenaxer> the stack is pre-filled with a mark bit
<beneroth> I would think one doesn't spawn new coroutines all the time, but initializes a bunch of them and then feed them with work whenever needed
<Regenaxer> Then 'stack' looks how many bytes are non-touched
<beneroth> ah nice idea
<Regenaxer> Exactly
<Regenaxer> So there is no cost at runtime
<Regenaxer> And I think it is worth
<Regenaxer> We can go with smaller stack segments
<Regenaxer> Without it it is nearly impossible to estimate the stack needs
<beneroth> yeah. that is really needed if one wants to do fine-tuned optimizations
<Regenaxer> T
<Regenaxer> And interesting things like simulations need very many coroutines
<beneroth> for use cases where that is not needed, the extra cost does not matter
<beneroth> exactly<
<Regenaxer> T
<Regenaxer> Here on my phone the startup time for a co with 64 kB stack increased from 0.6 to 2.1 millisecs
<beneroth> :DD
<Regenaxer> if only 10 kB stack, then it starts in only 0.8 millisecs
<beneroth> one initial iteration for the marking?
<Regenaxer> It goes linear with stack size naturally
<Regenaxer> It is a 'memset'
<beneroth> thought so
<Regenaxer> depends on the CPU
<beneroth> I see
<Regenaxer> On x84 it is a single instruction
<Regenaxer> rep stosw
<Regenaxer> rep stosq
<Regenaxer> stosb stores a byte each time
<Regenaxer> stosq 4 bytes iirc
<Regenaxer> for Arm I don't remember
<Regenaxer> Perhaps no dedicated instruction
<Regenaxer> thus an assembly loop storing 8 bytes each time
<Regenaxer> So I try on Debian now
<Regenaxer> Oh, btw, the above numbers are microseconds, not milliseconds :)
<Regenaxer> I do (bench (do 1000000 (co 'nop NIL)))
<Regenaxer> gives 2.1 secs on OnePlus phone
<Regenaxer> Oh, on x84 it is slower: 3.413 sec
<Regenaxer> Normally this machine is faster
<Regenaxer> But no worries about a few micro secs :)
<beneroth> T
<beneroth> bbl
<Regenaxer> cu :)
<tankf33der> $ pil +
<tankf33der> : (bench (do 1000000 (co 'nop NIL)))
<tankf33der> 2.257 sec
<tankf33der> real server
<Regenaxer> Thats better than here
<Regenaxer> here is an 8-Core 1996.260 MHz
<Regenaxer> but the above bench is 3.431 sec
<Regenaxer> on Termux/phone it is 2.135 sec
orivej has quit [Ping timeout: 240 seconds]
orivej has joined #picolisp
beneroth has quit [Quit: Leaving]
wineroots has quit [Remote host closed the connection]
mtsd has quit [Ping timeout: 240 seconds]
orivej has quit [Ping timeout: 240 seconds]