Composable Architecture Performance: Case Paths

Episode #152 • Jul 5, 2021 • Subscriber-Only

This week we improve the performance of another part of the Composable Architecture ecosystem: case paths! We will benchmark the reflection mechanism that powers case paths and speed things up with the help of a Swift runtime function.

Case Paths
Introduction
00:05
Case paths: a recap
01:35
Benchmarking case paths
09:27
Comparing cases using the Swift runtime
16:44
Failing fast with caching
22:53
Failure vs. success in isowords
26:56
Conclusion
30:29

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

Last week we explored performance in the Composable Architecture. We looked at the tools it comes with that help you troubleshoot and improve application performance, and we also fixed some longstanding performance problems that existed in the library itself.

But we’re still not quite done making performance improvements, because just after we recorded and edited that episode we found yet another opportunity to eke out more performance. There’s another part of the library that isn’t as efficient as it could be, and that’s in a dependency that the library heavily leans on to earn the “composable” in its name: and that’s Case Paths.

Case paths are a topic we introduced more than a year and a half ago when we theorized what key paths would like look for enums. Swift’s key paths are a wonderful feature that allow you to write algorithms over the shape of a struct by isolating a single field from the rest. Our case paths do the same, except they isolate a single case from the rest of an enum.

We were even able to make case paths as ergonomic as key paths. Just as the compiler generates a key path for each field of a struct automatically, we were able to automatically generate a case path for each case of an enum by making use of Swift’s reflection APIs. We even introduced a prefix operator so that the actual syntax looks similar to key paths.

In those episodes we stressed that reflection can be difficult to get write since you are operating outside the purview of the compiler, but even worse, it can also be quite slow. Using reflection APIs creates a lot of unnecessary objects, and unfortunately this penalty shows up in case paths.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

References

Collection: Case Paths

Brandon Williams & Stephen Celis • Monday Jan 20, 2020

The series of episodes in which Case Paths were first theorized and introduced.

Key paths are an incredibly powerful feature of the Swift language: they are compiler-generated bundles of getter-setter pairs and are automatically made available for every struct property. So what happens when we theorize an equivalent feature for every enum case?

How Mirror Works

Mike Ash • Wednesday Sep 26, 2018

A post on the official Swift Blog explaining how Swift’s reflection APIs work, including calls to functions that live on the runtime metadata, like the enum tag code we use in this week’s episode.

The Swift Runtime

Jordan Rose • Monday Aug 31, 2020

A series of posts on the Swift runtime.

Echo

Alejandro Alonso

A complete reflection library for Swift.

Downloads