Over the past few months, I’ve been building a concurrency framework in Odin called Tina.
My goal was to combine the fault-tolerance model of Erlang/OTP with the mechanical sympathy of Seastar (and a few ideas from reading the works of the folks at TigerBeetle).
Odin’s data-oriented design philosophy made me decide to implement my design in Odin, although my initial plan was to do it in Zig. I am sharing it here to get your feedback and any architectural critique.
Tina is a strictly bounded, shared-nothing concurrency framework. It operates on a few absolute constraints:
Thread-per-Core (Shards): Tina does not use work-stealing. Each OS thread (a “Shard”) is pinned to a core and runs its own cooperative scheduler.
Isolates & Effects: You do not write callbacks, promise, or async/await. You write “Isolates” (state machines, like Erlang processes) that react to messages and return Effect values (e.g., .receive, .io, .call, .reply). The framework interprets the Effect and handles the scheduling/dispatching.
Static Allocation: Tina performs zero dynamic allocations after boot. At startup, each Shard allocates a single “Grand Arena.” All mailboxes, I/O buffers, and typed arenas for the Isolates are carved out of this. If a mailbox fills up, ctx.send() returns .mailbox_full. The system sheds load rather than OOM-crashing.
100% Deterministic Simulation Testing (DST)
Because Tina abstracts the clock, network, and I/O backend (io_uring/kqueue/IOCP), the entire framework can run in a single-threaded simulation loop. Same seed + Same boot spec = Same execution order. You can inject network partitions, dropped messages, and simulated disk latency to find race conditions instantly, and reproduce them perfectly. This also works nicely with Odin’s test package, because you can use t.Seed and get your test replayable.
I published some docs today which should *hopefully make it easy to understand why certain things are designed the way they are, and how to explore them and build various programs (e.g. network proxy, http libraries…). There are examples on non-blocking TCP server and client, guides on non-blocking I/O.
I would highly value any code review, specifically regarding the memory allocation boundaries and the sigaltstack trap boundary used for Tier 2 fault containment.
Very well documented and complete with examples. I’m not currently working on anything that would benefit from this, but if I ever do, I’ll be sure to look this up again.
This seems really cool, and I love all the influences this project pulls from!
It would be nice to see more examples of things you can do with this (perhaps the TCP echo server should be proof enough, but I’m not expert enough to know what other problems have the same shape as a TCP echo server).
It would also be cool to see performance and feature comparisons to other concurrency frameworks, like:
Intel’s oneApi Thread Building Blocks (TBB)
Rust’s Rayon
Rust’s Tokio
Go’s goroutines
serverless Function as a Service architectures
(these are just some that I know about off the top of my head - not a comprehensive list)
In the readme, it would be interesting to see where Tina sits among these other frameworks/approaches, and also to see what problems Tina solves well vs. what problems Tina might be overkill for.
I think the deterministic/Tiger Beetle approach of Tina is pretty intriguing.
It’s tricky making examples because different folks are familiar with different domains. If you have something in mind you’d like to try it out with, shoot me a message either here, on Discord, or open a GitHub discussion in the repo. The concepts are a bit different, so it would require shaping the application a bit different than what you’d do with async/await or coroutines.
There’s examples of non-TCP work (might be similar to what you’d use Rust Rayon for). If you’re coming from Rust, you can use it to achieve the same thing you use Tokio + Rayon for, without shooting yourself in the foot like this example.
However, I’m working out a HTTP server as a library, as that seems to be what many would be familiar with (and hopefully show how to compose Tina’s core primitives to higher level protocols or libraries). So keep an eye for it
It would also be cool to see performance and feature comparisons to other concurrency frameworks,
I’m not focused on making performance comparison yet, because a good benchmark would take time to build and get right. The primary goal is to get things functionally working well, and the API surface good enough. Then some adoption and feedback, and anyone exploring it can run and share their own benchmarks.
That said, if you have something in mind, let me know how I can help you kick start it.
Thanks for the follow-up! I want to write an extremely simple hardware simulator example and then see if I can use Tina for scheduling different workers, and maybe do a comparison between single-threaded mode, Tina, and to some other concurrency approach. I’m doing a little work on that now.
In general, I think it would be nice to have more examples to play around with to get a sense of what Tina can do for me as a perspective user.
Do you have a note on what you’re trying to achieve? perhaps a small (rough) design note that’s not dependent on any concurrency approach? That way I can better suggest were to look.
We can discuss it on Discord (pmbanugo), LinkedIn, or email (whatever you prefer). I can share the details on a private message here.
The basic idea is that you have a hardware simulator where each module gets “clocked” and runs some code to pass signals/data from inputs to output FIFOs, and these output FIFOs copy their data to other modules’ inputs. So perhaps Tina can be a good fit here, but I don’t have an Odin code base to show for it yet - it’s just in the idea phase. So I’m trying to write something in my spare time so I can compare different approaches.
I added a HTTP package to Tina, and just published this blog about it. Maybe that’ll give a better idea of how to use it. And there’s code on GitHub if you want to dig deeper.
Hopefully it gives you a better understanding of the core. I have a large rewrite of the core scheduling algorithm, so hopefully after that I can polish some parts of the doc and focus on more examples and usecase.
I had toyed around with Odin for a different project. So it was the freshest in my mind and I decided to go with. But when I started designing how I expect the system to work, it was language agnostic such that Zig or Odin should work (perhaps C as well, but I never considered C).
Hi, it reminds me a lot of Glommio in Rust ecosystem. I think this is where your comparison could start and show strength/weakness of Odin vs Rust. (Just an idea!)
Thread-per-core is a concept used in low-latency/high-throuput systems like financial markets exchanges etc. Aeron is currently most well known system that promotes usage of thread-per-core execution.