Remix.run Logo
tristenharr 7 days ago

Happy new year HN! After a few late nights this past week, I've finally got this one over the finish line just in time to kick the year off.

I'm happy to answer any questions that might pop up...

Some things of note:

Built-in P2P Mesh Networking

Listen on "/ip4/0.0.0.0/tcp/8080". Connect to "/ip4/192.168.1.5/tcp/8080". Sync counter on "game-room".

That's all you need for libp2p, QUIC transport, mDNS discovery, GossipSub pub/sub

Full conflict-free replicated data types: - GCounter, PNCounter — distributed counters - ORSet with configurable AddWins/RemoveWins bias - RGA, YATA — sequence CRDTs for collaborative text editing - Vector clocks, dot contexts, delta CRDTs

Wrap any CRDT in Distributed<T> and get: - Automatic journaling to disk (CRC32 checksums, auto-compaction at 1000 entries) - Automatic GossipSub replication to all peers - Unified flow: Local mutation → Journal → Network. Remote update → RAM → Journal. - Survives restarts, offline nodes, network partitions.

Go-Style Concurrency - TaskHandle<T> — spawnable async tasks with abort - Pipe<T> — bounded channels (sender/receiver split) - check_preemption() — cooperative yielding every 10ms for fairness

There's more... but those are my personal favorite features.

I've put a good bit of work into this, so I hope you all can appreciate and maybe find some uses for it here on my favorite place on the interwebs!

tombert 4 days ago | parent | next [-]

These features seem considerably more interesting than the "English to Rust" feature. These data structures and the concurrency stuff seems pretty neat.

nextaccountic 3 days ago | parent | prev | next [-]

> Wrap any CRDT in Distributed<T>

Is this in a crate in crates.io?

tristenharr 3 days ago | parent [-]

Crates coming soon! :)

koakuma-chan 4 days ago | parent | prev [-]

Do I really want to yield every 10 ms?

gpm 4 days ago | parent [-]

You already do, to the kernel. It's probably not much more costly to do so an extra time in userspace.

koakuma-chan 4 days ago | parent [-]

I yield to the kernel to allow other threads that do some kind of background work to run. Do I want my application's async tasks to yield every 10ms? I assume that is what is being meant here.

tristenharr 4 days ago | parent | next [-]

That is a valid concern! To clarify:

Configurability: We absolutely plan to make the 10ms yield interval configurable (or opt-out) in the runtime settings. It is currently a default safety rail to prevent async starvation, not a hard constraint.

Concurrency Options: It is important to note that LOGOS has three distinct execution primitives, and this yield logic doesn't apply to all of them:

Simultaneously: (Parallel CPU): This compiles to rayon::join or dedicated std::threads. It does not use the cooperative yield check, allowing full blocking CPU usage on separate cores.

Attempt all: (Async Join) & Launch a task: (Green Threads): These compile to tokio async tasks. The cooperative yield is specifically here to prevent a single heavy async task from blocking the shared reactor loop.

So if you need raw, uninterrupted CPU cycles, you would use Simultaneously, and you wouldn't be forced to yield.

nextaccountic 3 days ago | parent | prev [-]

with cooperative scheduling, yes. This is indeed something missing from the Rust async ecosystem, tasks are meant to be IO-bound and if they become CPU-bound accidentally they will starve other tasks (async-std tried to fix this, but had some backlash due to overhead IIRC). Go actually puts a yield on every loop body (or used to), to prevent starvation. A 10ms thing will have negligible impact

Also: yielding to the kernel is very costly. Yielding to another task in your own thread is practically free in comparison