concurrencyerlangzig

Zig Concurrency Vs Erlang Concurrency, is Zig less efficient than Erlang?


I wrote the following two examples to test the concurrency of Zig and Erlang.

% Erlang
-module(spwntest).

disp()->
    _ = 234.
    
main(_) ->
    F = fun(_) -> spawn(fun() -> disp() end) end,
    lists:foreach(F,lists:seq(1,2000000)),
    io:format("done").

%% Result: All Erlang processes complete their work in less than 10 seconds

//!Zig


const std = @import("std");

pub fn main() !void{
    
    for(0..100000) |_|{
        const t = try std.Thread.spawn(.{},disp,.{});
        t.join();
    }
    
    std.debug.print("done",.{});
}

fn disp() void{
    _ = 10;
}

Result: Zig takes a lot of time for all threads finish their work.

According to my understanding, Erlang processes are more efficient and help develop scalable applications when compared with Zig concurrency.

I want to know from the opinions of experts to help my understanding.


Solution

  • There is no concurrency in your Zig code. You call join after creating each and every thread. This makes your code sequential. Also, std.Thread.spawn creates an OS thread. Whereas in Erlang spawn creates something else. From Wikipedia:

    They are neither operating system processes nor threads, but lightweight processes that are scheduled by BEAM. Like operating system processes (but unlike operating system threads), they share no state with each other.

    Here's the corrected code:

    const std = @import("std");
    
    pub fn main() !void {
        const count = 100000;
        var threads: [count]std.Thread = undefined;
    
        // spawning threads
        for (0..count) |i| {
            threads[i] = try std.Thread.spawn(.{}, disp, .{});
        }
    
        // waiting for all threads to finish
        for (0..count) |i| {
            threads[i].join();
        }
    
        std.debug.print("done", .{});
    }
    
    fn disp() void {
        _ = 10;
    }