# Fiber-local state?

**URL:** <https://forum.crystal-lang.org/t/fiber-local-state/2733>\
**Category:** Help & Support\
**Created:** [December 3, 2020, 4:57am UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733 "2020-12-03T04:57:12Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jgaskins](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jgaskins/32/2449_2.png) [@jgaskins](https://forum.crystal-lang.org/u/jgaskins)\
**Post date:** [December 3, 2020, 4:57am UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/1 "2020-12-03T04:57:12Z")

</div>

Trying to come up with a way to store state specific to a fiber that will get mopped up when the fiber completes. One thing I tried was to [add ivars to `Fiber`](https://github.com/jgaskins/datadog/blob/06470083cb6a66404fd5d08103eb4d1a1ac5684e/src/datadog.cr#L5-L8), but that may have performance implications since that makes every fiber take up additional heap memory, including fibers that would not store anything in them, and [more bytes per allocation requires more time](https://gist.github.com/jgaskins/dc347dfa62f275a4c9563db90b900f12) (this surprised me when I discovered it). In the grand scheme of things, it might not have a huge impact on either allocation/GC time or memory used, but I haven’t benchmarked in a real application yet.

Another idea was to maintain fiber-local state in a separate data structure and monkeypatch `Fiber#finalize` to remove itself from it. The hard part about using this as a pattern is that other libraries may have to do it, too, so we would have to call `previous_def` to invoke a previously defined monkeypatch for it.

In order to support this pattern, though, `Fiber` would need to define a no-op `finalize` method. This could also have performance implications since the GC would then register a finalizer for every fiber, regardless of whether it needs it. I don’t know how much performance that requires.

Are there other ways to do fiber-local state that don’t have the potential to slow down an application?

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [December 3, 2020, 2:02pm UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/2 "2020-12-03T14:02:03Z")

</div>

I don’t think that adding a couple of ivar in the Fiber is a bad thing, but yeah, the penalty exists.  
I think Fibers could be subclassed. I don’t recall anything in the runtime that forbids it.  
I’m in favor of adding protected methods to reduce the monkey-patching needed.

Yet two other routes could be:

a) mimic `Crystal::ThreadLocalValue` for fibers, to have an external hash from fiber =\> value. you would still need a monkey-patch to release the entries when a fiber finishes.

b) (ab)use the fiber stack to store some data. There is memory available there… I guess it can be used. It would be like reserving part of the stack for additional fiber runtime memory. If so, either that data need to be added as gc root at before\_collect or the stackbottom/top need to cover them to avoid collection. Also the stack are stored in a pool and are reused.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [December 3, 2020, 3:03pm UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/3 "2020-12-03T15:03:35Z")

</div>

Could we implement point 1? I think the solution is really nice, and it would be nice if it were supported by the standard library.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 3, 2020, 3:54pm UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/4 "2020-12-03T15:54:26Z")

</div>

That would probably be an excellent use case for nurseries that manage the lifecycle of fibers =\> [https://github.com/crystal-lang/crystal/issues/6468](https://github.com/crystal-lang/crystal/issues/6468)

Apart from that, adding a custom ivar to `Fiber` shouldn’t have much impact. Your benchmark surely measures something, but it’s not influenced by allocation size. Replacing all classes with structs yields pretty similar results (I’ve left a comment on the gist).

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [December 3, 2020, 6:27pm UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/5 "2020-12-03T18:27:30Z")

</div>

> [@bcardiff](#):
>
> you would still need a monkey-patch to release the entries when a fiber finishes.

To be clear, this is needed because the hash is external, not part of the `Fiber` type? Otherwise the value would be GC’d automatically?

I’m also interested in this feature. For my DI shard I’m doing this at the moment:

```auto
# :nodoc:
class Fiber
  property container : ADI::ServiceContainer { ADI::ServiceContainer.new }
end

```

This works quite well, as i can then just have a class method that is just `Fiber.current.container`. However I imagine this has some perf overhead, so deff interested in something more official to handle this.

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [December 6, 2020, 3:44am UTC](https://forum.crystal-lang.org/t/fiber-local-state/2733/6 "2020-12-06T03:44:26Z")

</div>

> [@Blacksmoke16](#):
>
> To be clear, this is needed because the hash is external, not part of the `Fiber` type? Otherwise the value would be GC’d automatically?

Exactly
