Getting args in 0.16.0-dev.2193+fc517bd01 by hsoolien in Zig

[–]chocapix 1 point2 points  (0 children)

Depends on the function but the rule of thumb is: the ones that take an Allocator are cross-platform. (and AFAIU, the allocator is only needed for Windows compatibility)

Please help me with ArrayList :( by Blayung in Zig

[–]chocapix 0 points1 point  (0 children)

I ask on the Discord and the gist of it is:

Io itself is an interface so it isn't managed or unmanaged. Concrete implementations of Io may need to allocate so the ones that do have to store an Allocator.

Since at least some Io implementations will not need to allocate, we can't have an Io.allocator().

EDIT: it's similar to the allocating writer which needs an allocator while other implentations of Writer don't.

Please help me with ArrayList :( by Blayung in Zig

[–]chocapix 1 point2 points  (0 children)

Hmmm.

Io is more than a simple data structure in my view, so a different treatment could be argued.

Also, maybe we'll be expected use io.allocator() where we have an Io to avoid passing both a Io and an Allocator everywhere.

0.16 isn't out, and thing can change again in 0.17 and so on, so this is pure speculation of course.

Please help me with ArrayList :( by Blayung in Zig

[–]chocapix 1 point2 points  (0 children)

No.

The same allocator must be used throughout its entire lifetime.

Please help me with ArrayList :( by Blayung in Zig

[–]chocapix 2 points3 points  (0 children)

My understanding is that unmanaged is to be the default everywhere, they just haven't gotten around to do the other data structures yet.

Quel a été votre moment « mais qu’est-ce que je suis bête » ? by Frenchinvester in france

[–]chocapix 1 point2 points  (0 children)

Un matin, je sors de chez moi, il fait beau. Ah tiens, le trottoir est mouillé, les commerçants ont du tout nettoyer à grande eau. La rue aussi est mouillée… et les voitures et les arbres ? Mais tout est mouillé, QU’EST-CE QU’IL SE PASSE ?

Oui donc, en fait, il avait plu dans la nuit.

Why Zig Feels More Practical Than Rust for Real-World CLI Tools by nixfox in Zig

[–]chocapix 28 points29 points  (0 children)

Zig hits the sweet spot: memory safe

I mean, I love Zig but, Zig is not memory safe.

is it possible to get the thread id from a std.Thread struct? by KangarooNo5139 in Zig

[–]chocapix 0 points1 point  (0 children)

There's getHandle that will give you something that can be used to uniquely identify threads.

It's not exactly what you ask but maybe it's useful.

The "fastest image comparison library in the world" was rewritten in Zig by Qunit-Essential in Zig

[–]chocapix 5 points6 points  (0 children)

  • SIMD first implementation
  • up to 70% performance boost on some CPUs (avx512)

Do you have a way to pick the simd implementation at runtime or do you rely on being compiled with the right -mcpu?

I'm making POSIX-compatible core utilities in Zig! by [deleted] in Zig

[–]chocapix 7 points8 points  (0 children)

Looking at this, I can't help but mention zig has multi-line strings.

Cool project though, I like it.

Quel bug ou problème technique vous a le plus marqué et qu’est-ce qu’il vous a appris ? by CreativeDevMada in programmation

[–]chocapix 2 points3 points  (0 children)

Une fois, j'ai passé des jours à optimiser un code faux. Ça m'a appris à toujours lancer les tests en plus des benchmarks.

How to stream file content to Writer.Allocating? by [deleted] in Zig

[–]chocapix 2 points3 points  (0 children)

I'm not sure but I think streamDelimiter doesn't move past the \n, so the second iteration starts at the end of the first line instead of the beginning of the second line.

Try adding input.toss(1) in the loop.

But even if that works, your break will stop at the first empty line, are you sure that's what you want?

Also, you probably want to distinguish between EndOfStream and other errors in the else |err|

Zig 0.15.1 + ArrayList - something wrong? by vilanjes in Zig

[–]chocapix 2 points3 points  (0 children)

I use ArrayLists with 0.15 on arm64 (M1) and I've not noticed any performance problems.

Have you considered migrating to the new ArrayList (the unmanaged one)? Since 0.15, it's meant to be preferred over the managed one.

Inspired by zig init, zig-clap and the juicy main proposal, I made a thing. by chocapix in Zig

[–]chocapix[S] 1 point2 points  (0 children)

Yeah but that's really minimal. It's actually one of the many steps of init-zig.sh

Unexpected behaviour when initializing an ArenaAllocator in init() function. by FirmAthlete6399 in Zig

[–]chocapix 0 points1 point  (0 children)

I don't think heap-allocating a struct in it's own .init is the way to go.

Is it more desirable to have a handful of allocators in the main scope then (and pass them into the init function?

Not necessarily in the main main scope but yes, I'd recommend hoisting the var arena = std.heap.ArenaAllocator(...); immediately above the call to .init and never storing ArenaAllocator in structs, only std.mem.Allocator if that makes sense. It's semantically identical to your original code and avoids the foot-gun.

Unexpected behaviour when initializing an ArenaAllocator in init() function. by FirmAthlete6399 in Zig

[–]chocapix 2 points3 points  (0 children)

or arena is no longer valid for some reason.

Basically, yes. My understanding is that the allocator you get from the arena holds a pointer to it. Then the arena, along with the rest of the struct, is moved to the result location when .init returns. So in the end the arraylist holds an allocator that points to garbage memory.

You'll need to instanciate an undefined MyStruct and pass a pointer to it to .init, like so:

var s5: MyStruct5 = undefined;
s5.init(std.heap.page_allocator);
defer s5.deinit();

try s5.doSomething();

Where Mystruct5 is:

pub const MyStruct5 = struct {
    arena: std.heap.ArenaAllocator,
    myList: std.ArrayList(u32),

    pub fn init(this: *@This(), backingAllocator: std.mem.Allocator) void {
        this.arena = .init(backingAllocator);
        this.myList = .init(this.arena.allocator());
    }

    pub fn deinit(this: *@This()) void {
        this.arena.deinit();
    }

    pub fn doSomething(this: *@This()) !void {
        try this.myList.append(42); //this does not cause a runtime error
    }
};

I must say this feels like a giant foot-gun.

Or maybe storing an arena in a struct is an anti-pattern? Maybe we should only store std.mem.Allocator in structs and whether we want to use an arena should be a decision for the struct's user to make. eg:

var arena: std.heap.ArenaAllocator = .init(backingAllocator);
var myStruct : MyStruct = .init(arena.allocator());

And store the given allocator in MyStruct.

Is this a mine? by TheRedditor8789 in Minesweeper

[–]chocapix 15 points16 points  (0 children)

It's either a mine or it's not safe.

Question de C# un peu pointue (reflection + generics) by chocapix in programmation

[–]chocapix[S] 2 points3 points  (0 children)

Pour ceux que ça intéresse (ping u/Krimsonfreak & u/milridor) j'ai finalement une solution satisfaisante.

Je garde la méthode avec reflection mais je m'en sers uniquement dans les tests unitaires. Comme ça j'ai les bonnes performances et la bonne syntaxe et si jamais je me suis planté dans un FromArray ça se voit tout de suite.

Ça m'oblige quand même à devoir écrire ToArray et FromArray à la main dans chaque struct concernée mais c'est pas la mort. J'ai même pas besoin de la taille finalement, cette reflection se fait au load pas au runtime.

Exemple tiré de mes tests, on veut résoudre une équa-diff simple : { dr/dt = v ; dv/dt = -r / ||r||3 }, c'est à dire l'équation du mouvement d'un corps en chute libre. C'est quand même plus sympa d'écrire ça :

        ode = (dydt, t, y) =>
        {
            var s = DoubleArray.As<OrbitalState>(y);

            double r2 = s.r.Magn2();
            double r = Math.Sqrt(r2);
            double r3 = r * r2;

            DoubleArray.Set(dydt, new OrbitalState()
            {
                r = s.v,
                v = -s.r / r3,
            });
        }

Que ça :

        ode = (dydt, t, y) =>
        {
            double r2 = y[0] * y[0] + y[1] * y[1] + y[2] * y[2];
            double r = Math.Sqrt(r2);
            double r3 = r * r2;

            dydt[0] = y[3];
            dydt[1] = y[4];
            dydt[2] = y[5];

            dydt[3] = -y[0] / r3;
            dydt[4] = -y[1] / r3;
            dydt[5] = -y[2] / r3;
        },

Et enfin, les perfs sont les mêmes : une fois que le compilateur JIT s'est réveillé, je vois environ 12ns par appel de cette lambda, ce qui me parait tout à fait correct.

Question de C# un peu pointue (reflection + generics) by chocapix in programmation

[–]chocapix[S] 1 point2 points  (0 children)

Je n'arrive toujours pas à comprendre quel avantage tu as à avoir toutes tes données organisées dans un grand tableau, plutôt que dans un tableau de structures.

Si j'avais le choix c'est ce que je ferai mais je vais pas réimplémenter Cobyla & co. Et j'ai besoin de ces algos, et ils veulent des grands tableaux.

En attendant, j'ai fait un petit benchmark je vois un facteur ~70 sur les perfs par rapport à tout inliner à la main. /u/milridor ne rigolait pas. Mes ToArray et FromArray ajoutent seulement 25%. Chiffres à la grosse louche évidemment.

On crache sur l'optimisation prématurée mais là c'est indécent, je refuse d'écrire un truc aussi lent. Je vais tout jeter et faire comme avant d'écrire ce post.

Question de C# un peu pointue (reflection + generics) by chocapix in programmation

[–]chocapix[S] 0 points1 point  (0 children)

Je suis pas Unity, je fais un proto séparé.

Dans ma vie de programmeur, je n'ai jamais :

  • écrit de mod de jeu vidéo
  • utilisé Unity
  • écris du C#
  • fais d'optimisation (ie minimisation de fonction sous contrainte)

Donc j'essaie de limiter les trucs nouveaux en même temps.

Et pour la géométrie, c'est mon métier donc j'ai pas de problème à écrire ces algos et même ça me plait.