v3.6.0
This is the fifty-fifth 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. Please note that we did break binary compatibility with 3.6.0 RC1 (not with 3.5.x) in order to fix some things, so if you published anything against that release you will need to reconsider your life choices.
[!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 is already under development and we plan to release it in 3.7.0 as soon as possible.
What's Changed
This release contains the largest change to the Cats Effect internal work scheduler since the introduction of work stealing back in the run up to 3.0.0. In particular, we have finally completed implementation of the integrated runtime we first conceived of back in early 2022. Well, I say "we", but really @armanbilge deserves the absolute lion's share of the credit here. He did almost all of the work not only on the direct implementation in Cats Effect, but also the downstream functionality built on top of it in Fs2 and in Http4s… not only on the JVM but also in Scala Native and across multiple operating systems! It is hard to overstate how gargantuan of an effort this was, both in design and implementation.
As immense as the effort has been, the impact is even more dramatic. We've already observed scenarios in which the performance of microservices implemented on top of Http4s Ember on the JVM leveraging io_uring is improved by over 3.5x! That is to say, the performance is 3.5x higher than baseline using classical NIO2! (as measured by TechEmpower, suggesting performance more than 2x higher than pekko-http) Now, TechEmpower does have its limitations as a framework, but it does represent a useful standard candle for certain access patterns, and improving an already very fast trio of frameworks by this magnitude is not something that happens every day. Even more excitingly, this is just the tip of the iceberg! We ran these tests with very early, almost PoC code with a lot of performance-impacting caveats. The best is yet to come.
And if that wasn't enough, the biggest impacts are not on the JVM but actually on Scala Native. Without diving too far into the details, this type of syscall scheduling mechanism is exactly what is necessary on Scala Native to achieve any measure of performance from downstream services. It is actually remarkably similar to what the Go runtime does, though implemented in a more extensible way (e.g. Go does not, at present, have native support for io_uring, whereas Cats Effect can and has implemented this via a third-party library).
Going forward, Cats Effect will be maintaining support for the following polling systems:
- JVM
Selector
- Native
- kqueue
- epoll
Support for io_uring is already under heavy development, and we expect to incorporate this into Cats Effect at some future date, supporting both Native and JVM. The integrated runtime was specifically designed with io_uring's unique data patterns in mind and we have already been able to demonstrate that downstream layers of the ecosystem will be able to fully leverage its benefits. Additionally, we believe we can meaningfully improve JVM performance by implementing epoll and kqueue support for the JVM (and not just Native), the former for situations where io_uring is unavailable. This is mostly because Selector is actually very very slow, and while the performance of the Selector-based runtime is roughly on par with what we've been able to achieve on top of NIO2 (which has its own syscall management and is incompatible with the integrated runtime), we know we can do quite a bit better.
On top of the above, this release contains a large number of other enhancements covering a number of major scenarios. Most noticeably, thanks to @kamilkloch, explicitly importing cats.syntax.all._ is no longer required for most usage involving explicit IO! You will still need the syntax import for any use of parametric effects (commonly referred to as "tagless final" or F[_]), and unfortunately due to the way Scala's type inference works, it is also required for the very common traverse function, but nearly any and all other cases have had their implicit search tweaked to avoid this inconvenience. This in turn means that . completion now mostly Just Works™ when using IO (and when it doesn't, hunting for methods on the IO companion object definitely works).
An additional class of work went into substantially improving the internal instrumentation and metrics associated with the runtime. As previously, these are all exposed as JMX MBeans on the JVM, but we have additionally added public APIs which allow applications to self-instrument (rather than forcing external untyped instrumentation via JMX). These metrics have been organized to mirror the structure of the runtime itself and can all be found within the cats.effect.unsafe.metrics package.
If you're an end-user of Cats Effect (in other words, you run applications built on Cats Effect, rather than building libraries or frameworks), one way you can very much aid the future development of the library is to incorporate these metrics (likely via JMX) into your application observability and key metrics. This should allow you to start to build up an intuition for what metrics are significant indicators of good or bad or just plain normal behavior. This is exactly the type of information that is difficult for library authors to realistically determine, but if end-users learn this on our behalf, you can help educate us on the precise details of how the runtime behaves for your application in your production context, shaping the future optimization and tuning of the framework! (note: Cats Effect does not proactively send metrics anywhere from your application, it merely exposes them to your own monitoring infrastructure)
Enhancements
- Polling system by @armanbilge in https://github.com/typelevel/cats-effect/pull/3332
evalOnExecutorby @homycdev in https://github.com/typelevel/cats-effect/pull/3691- Native signal handling and safe
IOAppcancelation by @armanbilge in https://github.com/typelevel/cats-effect/pull/3695 - Add
warnOnNonMainThreadDetectedconfiguration toIOAppby @diogocanut in https://github.com/typelevel/cats-effect/pull/3815 - Block in-place if running on a virtual thread by @armanbilge in https://github.com/typelevel/cats-effect/pull/3870
- Add
GenConcurrent#parSequenceN_andGenConcurrent#parTraverseN_. by @kamilkloch in https://github.com/typelevel/cats-effect/pull/3916 - Apply
@staticannotation internally by @armanbilge in https://github.com/typelevel/cats-effect/pull/3934 - Added
PriorityQueue{Sink,Source}extendingQueue{Sink,Source}by @neomaclin in https://github.com/typelevel/cats-effect/pull/3930 - Timer stealing without a concurrent data structure by @armanbilge in https://github.com/typelevel/cats-effect/pull/3781
- Embed
cats.syntax.all._intoIO. by @kamilkloch in https://github.com/typelevel/cats-effect/pull/3532 - Quick and dirty unsafe queue API by @djspiewak in https://github.com/typelevel/cats-effect/pull/3975
- Implement async dropping queue by @iRevive in https://github.com/typelevel/cats-effect/pull/4143
- Refactor
Ref#mapKto takeFunctor[G]constraint instead ofFunctor[F]by @armanbilge in https://github.com/typelevel/cats-effect/pull/4115 - Add
ownPollerby @armanbilge in https://github.com/typelevel/cats-effect/pull/4133 - Use
IO.unitinAsync[IO].unitby @iRevive in https://github.com/typelevel/cats-effect/pull/4162 - Add default constructor for
MapRefby @yisraelU in https://github.com/typelevel/cats-effect/pull/4139 - Add
SystemPropertiesby @massimosiani in https://github.com/typelevel/cats-effect/pull/3924 - Make
timeout/timeoutToalways return the outcome of the effect by @biochimia in https://github.com/typelevel/cats-effect/pull/4059 IOLocalpropagation for unsafe access by @armanbilge in https://github.com/typelevel/cats-effect/pull/3636- Make
UUIDGenmore performant by @diogocanut in https://github.com/typelevel/cats-effect/pull/3647 - from by @rossabaker in https://github.com/typelevel/cats-effect/pull/3429
Bug Fixes
- Join worker threads on pool shutdown by @armanbilge in https://github.com/typelevel/cats-effect/pull/3794
- Remove
IORuntimefromallRuntimeson shutdown by @RafalSierkiewicz in https://github.com/typelevel/cats-effect/pull/4090 - Make
IO#onErrorconsistent withApplicativeErrorby @lenguyenthanh in https://github.com/typelevel/cats-effect/pull/4121 - Implement a safer
Resource.attemptwhich releases acquired resource(s) in case of error by @lenguyenthanh in https://github.com/typelevel/cats-effect/pull/4128 - Removed implicit modifiers on deprecated instance to avoid unavoidable warnings by @djspiewak in https://github.com/typelevel/cats-effect/pull/4180
- Check target array length before allocating by @counter2015 in https://github.com/typelevel/cats-effect/pull/4159
- use worker thread index at startup by @biochimia in https://github.com/typelevel/cats-effect/pull/4197
- Blocked thread detection fixes by @biochimia in https://github.com/typelevel/cats-effect/pull/4195
- Fix MapRef.fromSeqRefs vulnerability by @underskyer in https://github.com/typelevel/cats-effect/pull/4208
- Fixed off-by-one error in other index selection by @djspiewak in https://github.com/typelevel/cats-effect/pull/4214
- Report non-fatal
Runnablefailures onMainThreadEC by @armanbilge in https://github.com/typelevel/cats-effect/pull/4223 - Always report timers/events when worker unparked by @armanbilge in https://github.com/typelevel/cats-effect/pull/4227
- Introduce
PollResult,PollingSystem#processReadyEventsby @armanbilge in https://github.com/typelevel/cats-effect/pull/4230 - Shutdown the runtime only when unforked by @armanbilge in https://github.com/typelevel/cats-effect/pull/4234
- Restore
ArrayBlockingQueuefor worker-to-blocking state transfer by @armanbilge in https://github.com/typelevel/cats-effect/pull/4255 - Refactor
WorkerThreadrunloop; avoid pathological starvation of pollers by @armanbilge in https://github.com/typelevel/cats-effect/pull/4247 - Transfer tick state when replacing a blocked thread by @armanbilge in https://github.com/typelevel/cats-effect/pull/4264
WorkStealingPoolMetrics->WorkStealingThreadPoolMetricsby @armanbilge in https://github.com/typelevel/cats-effect/pull/4271- Run finalizers in
IO#unsafeRunTimedby @armanbilge in https://github.com/typelevel/cats-effect/pull/4279 - Create
UnsafeNonFatalfor use in the fiber runtime by @kapunga in https://github.com/typelevel/cats-effect/pull/4263
Documentation
- Add Documentation to
PollingSystemby @antoniojimeneznieto in https://github.com/typelevel/cats-effect/pull/3752 - Remove an old comment by @lenguyenthanh in https://github.com/typelevel/cats-effect/pull/3897
- Changed tutorial so consumers are not overwhelmed by producers by @lrodero in https://github.com/typelevel/cats-effect/pull/3762
- Fix typo by @asakaev in https://github.com/typelevel/cats-effect/pull/3912
- fix typo in docs by @SethTisue in https://github.com/typelevel/cats-effect/pull/3984
- Fix typo in typeclasses.md by @berndlosert in https://github.com/typelevel/cats-effect/pull/3868
- Use
depinstead oflibin FAQ docs by @ChidiRnweke in https://github.com/typelevel/cats-effect/pull/3999 - Fix Gavin's name by @kubukoz in https://github.com/typelevel/cats-effect/pull/4020
- Remove CODE_OF_CONDUCT override, use org default by @valencik in https://github.com/typelevel/cats-effect/pull/4046
- Update copyright date by @geny200 in https://github.com/typelevel/cats-effect/pull/4060
- Fix versions in README.md by @durban in https://github.com/typelevel/cats-effect/pull/4062
- Added new fork gotcha to the docs by @kapunga in https://github.com/typelevel/cats-effect/pull/4084
- Fix typos by @bwignall in https://github.com/typelevel/cats-effect/pull/4100
- Fixes scaladocs for
asyncandasync_by @satorg in https://github.com/typelevel/cats-effect/pull/4102 - fixes and attempts to improve scaladoc for Outcome by @satorg in https://github.com/typelevel/cats-effect/pull/4111
- Update
onNonMainThreadDetected()warning by @Friendseeker in https://github.com/typelevel/cats-effect/pull/4188 - update
LocalQueuedocs/comments by @biochimia in https://github.com/typelevel/cats-effect/pull/4194 - Fix small typo in docs by @serragnoli in https://github.com/typelevel/cats-effect/pull/4257
- Document
Pollby @arturaz in https://github.com/typelevel/cats-effect/pull/4277
Behind the Scenes
- "completed" -> "succeeded" in
PollerMetricsby @armanbilge in https://github.com/typelevel/cats-effect/pull/4210 - Add JDK 21 to CI matrix by @armanbilge in https://github.com/typelevel/cats-effect/pull/3871
- Backport changes from minor branch by @djspiewak in https://github.com/typelevel/cats-effect/pull/3846
- Backport current changes from series/3.5.x by @djspiewak in https://github.com/typelevel/cats-effect/pull/3920
- Cherry-pick Cirrus CI updates to series/3.x by @armanbilge in https://github.com/typelevel/cats-effect/pull/3805
- Configure mergify to add :robot: label by @armanbilge in https://github.com/typelevel/cats-effect/pull/3630
- Delete .envrc by @armanbilge in https://github.com/typelevel/cats-effect/pull/4224
- Drop macOS jobs from Cirrus by @armanbilge in https://github.com/typelevel/cats-effect/pull/3832
- Fix bad merge by @armanbilge in https://github.com/typelevel/cats-effect/pull/3852
- Fix scaladoc, check in CI going forward by @armanbilge in https://github.com/typelevel/cats-effect/pull/4217
- Improve currently-failing tests by @djspiewak in https://github.com/typelevel/cats-effect/pull/4211
- Merge changes from 3.5.1 into series/3.x by @djspiewak in https://github.com/typelevel/cats-effect/pull/3708
- Merge changes from 3.5.2 into series/3.x by @armanbilge in https://github.com/typelevel/cats-effect/pull/3858
- Merge changes from 3.5.3 into series/3.x by @armanbilge in https://github.com/typelevel/cats-effect/pull/3958
- Merge changes from 3.5.4 into series/3.x by @djspiewak in https://github.com/typelevel/cats-effect/pull/4033
- Merge changes from 3.5.5 into series/3.x by @armanbilge in https://github.com/typelevel/cats-effect/pull/4155
- Merge changes from 3.5.6 into series/3.x by @samspills in https://github.com/typelevel/cats-effect/pull/4176
- Merge changes from 3.5.7 into series/3.x by @djspiewak in https://github.com/typelevel/cats-effect/pull/4184
- New year who dis by @djspiewak in https://github.com/typelevel/cats-effect/pull/4231
- Only run mdoc on Temurin 17 by @armanbilge in https://github.com/typelevel/cats-effect/pull/3921
- Organize imports rule is available out-of-the-box by @armanbilge in https://github.com/typelevel/cats-effect/pull/3667
- Refactor WSTP metrics by @armanbilge in https://github.com/typelevel/cats-effect/pull/4205
- Remove "metrics" that are
LocalQueueimplementation details by @armanbilge in https://github.com/typelevel/cats-effect/pull/4203 - Remove plugins we get transitively by @armanbilge in https://github.com/typelevel/cats-effect/pull/3798
- Skip starvation test (which is breaking CI) by @djspiewak in https://github.com/typelevel/cats-effect/pull/3928
New Contributors
- @homycdev made their first contribution in https://github.com/typelevel/cats-effect/pull/3691
- @diogocanut made their first contribution in https://github.com/typelevel/cats-effect/pull/3815
- @neomaclin made their first contribution in https://github.com/typelevel/cats-effect/pull/3930
- @SethTisue made their first contribution in https://github.com/typelevel/cats-effect/pull/3984
- @berndlosert made their first contribution in https://github.com/typelevel/cats-effect/pull/3868
- @ChidiRnweke made their first contribution in https://github.com/typelevel/cats-effect/pull/3999
- @geny200 made their first contribution in https://github.com/typelevel/cats-effect/pull/4060
- @kapunga made their first contribution in https://github.com/typelevel/cats-effect/pull/4084
- @RafalSierkiewicz made their first contribution in https://github.com/typelevel/cats-effect/pull/4090
- @satorg made their first contribution in https://github.com/typelevel/cats-effect/pull/4102
- @steinybot made their first contribution in https://github.com/typelevel/cats-effect/pull/4107
- @yisraelU made their first contribution in https://github.com/typelevel/cats-effect/pull/4139
- @massimosiani made their first contribution in https://github.com/typelevel/cats-effect/pull/3924
- @biochimia made their first contribution in https://github.com/typelevel/cats-effect/pull/4059
- @Friendseeker made their first contribution in https://github.com/typelevel/cats-effect/pull/4188
- @counter2015 made their first contribution in https://github.com/typelevel/cats-effect/pull/4159
- @satabin made their first contribution in https://github.com/typelevel/cats-effect/pull/4105
- @underskyer made their first contribution in https://github.com/typelevel/cats-effect/pull/4208
- @bio-aeon made their first contribution in https://github.com/typelevel/cats-effect/pull/4220
- @serragnoli made their first contribution in https://github.com/typelevel/cats-effect/pull/4257
Full Changelog: https://github.com/typelevel/cats-effect/compare/v3.5.7...v3.6.0