In this blog post, we will discuss fibers in ZIO, and how are they different from threads.
ZIO is a highly concurrent framework powered by fibers that are lightweight virtual threads. They enable tremendous scalability compared to threads and are reinforced with resource-safe cancellation, which supports several features in ZIO.
What are Fibers?
Fibers are lightweight equivalents of OS threads which represent an ongoing computation. A single fiber performs the instructions sequentially. A single JVM thread can run several fibers. So fibers have many to one relationship with threads.
Fibers in ZIO
In ZIO, all effects are executed by some fiber. If we did not create the fiber, then the fiber was created by some operation we are using (if the operation is concurrent or parallel), or by the ZIO runtime system.
Even if we just write “single-threaded” code with no parallel or concurrent operations, at least one fiber will exist i.e. the “main” fiber that executes our effect.
Every fiber either fails or succeeds depending on whether the effect it is executing succeeds or fails.
Similarities with Threads
ZIO fibers, just like operating system-level threads, have a well-defined lifespan that is dictated by the effect they are executing.
Fibers also contain distinct identities, stacks (including stack traces), local state, and status (such as done, running, or suspended).
Limitations of Threads
There are some limitations of operating system threads compared to ZIO fibers.
- Threads are scarce — Threads on the JVM map to threads on the operating system, limiting the number of threads we can have in our program.
- Expensive on creation — Generally thread creation is quite costly in terms of both time and memory complexity.
- Much Overhead on Context Switching — it takes a lot of time to switch from one thread’s execution to another.
- Lack of Composability — Threads do not have a meaningful return type. So they cannot finish with any specific value. Also, they have no type parameter for error.
Key features of Fibers
ZIO fibers attempt to address thread constraints by including features such as:
- Unbounded Size — the mapping of fibers to threads is many-to-one, thus fibers offer us massive concurrent lightweight green threading on the JVM.
- Lightweight — fibers are quite lightweight as they are virtual, and as they use green threading
- Asynchronous — Threads are always synchronous, whereas fibers are always asynchronous. That is why fibers outperform threads in terms of scaling.
- Typed and Composable — Fibers have a meaningful return type and allow us to write more type-safe programs. Fibers have typed error (E) and success values (A) as their type.
- Structured Concurrency — ZIO provides structured concurrency. The child fibers are scoped to their parent fibers. It means that when the parent effect finishes execution, then all child’s effects will be automatically interrupted. So when we fork, we get back a fiber. The fiber’s lifetime is bound to the parent fiber that forked it. It is almost impossible to leak fibers because child fibers are guaranteed to complete before their parents.
Fiber Data Type
Fiber data type in ZIO represents a “handle” on the execution of an effect. The
Fiber data type is most similar to Scala’s
Future data type, which represents a “handle” on a running asynchronous computation.
Fiber[E, A] data type in ZIO has two type parameters:
EFailure Type. The
Ecorresponds to the error channel. It indicates the error type with which the fiber can fail.
ASuccess Type. The
Acorresponds to the success value of the computation. That means fiber can succeed with type A
Fibers do not have an
R type i.e. the environment parameter, because fibers only execute effects that have already had their requirements provided to them.
In this blog, we discussed ZIO fibers, their features, and their similarity to threads. We also took a brief about fiber data type in ZIO. To read more blogs like this, do check out here
For exploring more regarding fibers in ZIO please refer to the following link