github typelevel/cats-effect v3.6.2

latest releases: v3.7.0-RC1, v3.6.3
one month ago

This is the fifty-seventh release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with the 3.6.x lineage.

Warning

Please note that Cats Effect 3.6.x is targeting Scala Native 0.4.x, which means it does not at present support native multithreading. This was a very intentional choice meant to give us an opportunity to break binary compatibility only on Scala Native if necessary when upgrading to Scala Native 0.5 and as we discover the impacts of the integrated runtime on the downstream ecosystem. It also reduces risk since Native multithreading in the runtime is a significant lift and we want to make sure we isolate that change from the already significant changes in 3.6.0. This functionality has already merged into the development branch and we plan to release it in 3.7.0 as soon as possible.

What's Changed

This release addresses a performance issue since 3.6.0 that was reported to be somewhat severe in applications which leverage asynchronous I/O without using the new polling system. Extensive discussion of this issue can be found in #4328. While a workaround was possible, the regression was certainly undesirable. We've changed the polling logic to be considerably less aggressive. In particular, threads will only poll if the polling system has outstanding events which require polling. This means that any applications which make no use of the polling system should see marginal (if any) overhead relative to pre-3.6 versions of Cats Effect, while applications which lean heavily on the new integrated runtime will still see the full benefits thereof.

Note that there is a somewhat pathological case here where an application makes use of the polling system (usually via some dependency, like Skunk or Ember), but does not make heavy use of that code path while simultaneously making very heavy use of other asynchronous I/O mechanisms (such as Netty or Blaze, often indirectly via other dependencies). In this scenario, the worker threads will be forced to make the more expensive polling syscalls, but those calls will often yield very small or empty batches while the majority of the work is enqueued externally (via other async I/O mechanisms). This will result in meaningful overhead relative to the theoretical optimal behavior.

We made the conscious decision in 3.6.0 to prioritize the performance of the integrated runtime, and while we certainly still want all use cases to behave as optimally as possible, this does mean that we occasionally needed to make some tradeoffs in order to achieve the performance goals we had in mind. Our hope is that as the ecosystem continues to adapt to the use of the integrated runtime (particularly with the rise of Scala Native 0.5, where there are essentially no other viable options), these edge cases will become quite rare.

Enhancements

Bug Fixes

Documentation

Behind the Scenes

New Contributors

Full Changelog: v3.6.1...v3.6.2

Don't miss a new cats-effect release

NewReleases is sending notifications on new releases.