scientes has quit [Remote host closed the connection]
scientes has joined #zig
jjido has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<daurnimator>
oh I only just noticed the allocator interface change
<daurnimator>
`([*]u8)(undefined)[0..0]` is... odd to me
<daurnimator>
I feel like every allocator is going to end up branching on old.len == 0.....
<daurnimator>
which makes me think the old interface made more sense...
<daurnimator>
same with shrink: almost every allocator is going to special case new_n == 0
<andrewrk>
what's the problem with that?
<daurnimator>
if you're essentially going to have two different code paths; it would be nicer to have them as two different functions
<daurnimator>
which means going via a single function is..... inefficient
<daurnimator>
==> I think the new reallocFn and shrinkFn are good. but the old interfaces should have been kept.
<andrewrk>
whether it's more or less efficient is hard to say. there is also the consideration that @sizeOf(Allocator) is now 16 instead of 24 on x86_64
<andrewrk>
I think that particular point is related to the new interface that Jimmi and tgshultz are working on
<daurnimator>
we now have two callbacks to expose those 4: reallocFn: 1, 2, 3, 4; and you can error on all of them. and shrinkFn which does 3, 4. but can't error.
<andrewrk>
5. shrink allocation but allow allocator to fail if it wouldn't be able to recover the bytes
<andrewrk>
(5) is the important new one that I added
<daurnimator>
andrewrk: is shrinkFn really different to `try reallocFn(...) catch error.OutOfMemory`
<andrewrk>
isn't that catch redundant?
<andrewrk>
`try reallocFn(...) catch error.OutOfMemory` is equivalent to `reallocFn(...)`
<andrewrk>
er wait why is there a try and a catch?
<daurnimator>
andrewrk: uh I meant to say: call reallocFn and suppress out of memory errors.
<andrewrk>
the difference is in what slice length and alignment the client will next use to call one of the allocator functions
<daurnimator>
I guess we have the subtle difference that reallocFn can move on a shrink, and shrink can't/
<andrewrk>
shrink can move on a shrink
<daurnimator>
or can shrink move as well?
<andrewrk>
but it cannot fail
<andrewrk>
the only difference is whether failure is allowed
<daurnimator>
okay so really shrink could be: call reallocFn and don't propagate errors.
<andrewrk>
// Guaranteed to be the same as what was returned from most recent call to
<andrewrk>
// `reallocFn` or `shrinkFn`.
<andrewrk>
that's an important guarantee the allocator is given
<andrewrk>
also the fact that realloc is allowed to fail is meaningful
<daurnimator>
andrewrk: okay.... but I'm not sure how that is relevant here?
<andrewrk>
if realloc fails then the allocation size and alignment properties are not updated. so the client must keep track of the size and alignment
<andrewrk>
shrink allows the client to track a new size & alignment
<andrewrk>
if we do some performance testing and find out that more interface functions is better for performance & memory, that's fine, we can do that
<andrewrk>
but that should happen after the new interface experiments are done
<andrewrk>
because this API makes sense in terms of semantics of implementing an allocator interface
<daurnimator>
andrewrk: ^ wouldn't that be correct?
<andrewrk>
not necessarily
<andrewrk>
for example in the general purpose debug allocator, it would cause crashes, because it does not update the old_size and old_align metadata
<andrewrk>
and so when the next realloc or shrink is called, it would detect that the client used an incorrect value for old_mem.len or old_alignment
<daurnimator>
andrewrk: hang on then.... what should shrink do if it can't satisfy the new alignment?
<andrewrk>
in a fast release mode allocator it could cause undefined behavior, because the allocator implementation may rely on the interface guarantee of old_mem.len and old_alignment being the same as what was returned from most recent call to reallocFn or shrinkFn
<andrewrk>
new_alignment is guaranteed to be <= old_alignment. so if shrink cannot find a preferable new location for the allocation, it should update any internal metadata structures, if any, and then return the same pointer sliced to the new_size
<andrewrk>
there is one more modification to the Allocator interface I am considering, which is a flag that indicates the Allocator is some sort of arena and frees are not necessary. perhaps this could be indicated by making shrinkFn optional, but I'm not sure. sometimes shrink can actually work even for arena allocators
<scientes>
ouch, NaN == NaN is a pretty serious bug
<andrewrk>
but the use case is that if you're given an opaque *Allocator, and you want to make an arena out of it, it's worth checking if it's already an arena. No point in doubling up
<daurnimator>
andrewrk: no problem with making shrink an empty function....
<daurnimator>
andrewrk: arenas of arenas are useful
<andrewrk>
daurnimator, if 2 arenas have no capability of freeing, then stacking them only wastes space
<daurnimator>
andrewrk: hmm. right.
* daurnimator
is trying to figure out why that didn't match his experience
<andrewrk>
"arena" is a broad concept. it's quite possible for an arena to also handle freeing
<andrewrk>
so this flag would only be set when an arena knows it has no capability of freeing. which is why it might make sense for it to have a null shrinkFn
<daurnimator>
right
<daurnimator>
so for our arenas, we allowed freeing within the arena
<daurnimator>
but *also* that it was super cheap to drop the whole arena at once
<andrewrk>
right. for that one you would not set the flag
<daurnimator>
andrewrk: I don't particularly see the benefit of no shrinkFn over empty-body shrinkFn.
<daurnimator>
andrewrk: btw.... another misc allocator parameter that would be interesting is zero-initialised.
<daurnimator>
some allocators (mmap) will provide pre-zeroed memory.
<andrewrk>
that would re-introduce the concept of zero initialization, which currently does not exist, and, in fact, was removed from an earlier version of zig
<daurnimator>
whereas a stack allocated FixedBufferAllocator would not.
<andrewrk>
scientes, the NaN == NaN issue is scheduled for 0.4.0
<daurnimator>
andrewrk: I feel like it might be more of an optimizer hint than anything else.... is there a way to tell llvm: "btw this memory is already 0; you can optimize out a following memset(0)"
<andrewrk>
but memset(0) would already be unlikely due to zig not having the concept of zero initialization
<andrewrk>
s/already//
<daurnimator>
andrewrk: hrm. would an `assert(mem.eq(i8, []i8{0} ** len, new_mem)` be enough to tell the optimizer?
<andrewrk>
the information would be there. I doubt the optimizer is intelligent enough to use it
<andrewrk>
it's always possible to add a custom pass to detect such patterns
<andrewrk>
but I have low expections of how much benefit that would bring
<daurnimator>
Though it doesn't really solve the puzzle of e.g. "i want a zero initialised vector" => lib_allocator.zAlloc() => should call calloc rather than malloc.
<daurnimator>
andrewrk: what if alloc/grow took a "initialisation value" parameter. could be `undefined` by default...
<andrewrk>
I did that and then reverted it because it causes an extra unnecessary copy
<andrewrk>
it violates no-copy semantics
<daurnimator>
oh?
<daurnimator>
andrewrk: what gets copied?
<andrewrk>
consider the example where you want one field of a struct to point to another one
<andrewrk>
if you initialize the allocated memory directly, it works. if you construct the initialization value and then pass it as a parameter, it has to get copied into place, violating the "fixed" field
<daurnimator>
what if the initialisation value was a i8?
<daurnimator>
hmmmm. the only "reasonable" initialisation values I can think of are undefined or 0
<daurnimator>
nothing else is really going to be beneficial
<daurnimator>
so really it could be a `zero: bool` parameter
<andrewrk>
Akuli, do you think I have been prioritizing my time suboptimally, or have been dishonest about zig's 32 bit linux support?
<Akuli>
no, i think that everyone knows that nobody uses 32-bit systems anymore, except for a few funny people who should just get a new laptop
<Akuli>
i'm not angry to anyone, it's fine to have no usable 32-bit support
<andrewrk>
apple has officially deprecated 32 bit hardware which is why that has Tier 4 support. Linux 32 bit support is still planned, it just takes some effort to get it up to speed
<scientes>
including armhf support
<Akuli>
i expected tier 2 to be usable
<Akuli>
maybe the readme should emphasize that only tier 1 actually works?
<scientes>
arm64/linux works
<scientes>
but yeah i386/linux doesn't really work
<scientes>
Akuli, how to I mark mines?
<Akuli>
:D did you read the help? make the terminal big enough and press h
<Akuli>
shorter answer: f
<andrewrk>
tier 2 means not guaranteed to be usable
<Akuli>
the readme game me the impression that it is usable even though it's not guaranteed to be usable
<andrewrk>
linux 32 bit is 10 minutes away from being usable by me or scientes
<scientes>
well zig is quite rough around the edges
<scientes>
still
<Akuli>
this game is about 2 hours away from being playable to me :(
<Akuli>
2 hours of porting it all to c, that is
* scientes
might take that as a challenge
<scientes>
and install a 32-bit user-land
<andrewrk>
you could probably rent a server for 2 hours for a few cents
<Akuli>
lol
gunnarahlberg has joined #zig
<andrewrk>
I can't remember if I posted this on IRC yet, but, new docs for Assembly and for zig test: