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
<
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>
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
<
Regenaxer>
yeah, interesting
<
beneroth>
will be useful
<
Regenaxer>
Seeing which variations consume stack
<
beneroth>
not using coroutines much yet, but I've got ideas
<
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>
: (stack)
<
Regenaxer>
-> ((nop . 63) (inc . 63) (T . 250) . 64)
<
Regenaxer>
: (co '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>
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>
Here on my phone the startup time for a co with 64 kB stack increased from 0.6 to 2.1 millisecs
<
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
<
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 :)
<
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]