The Wire · Showcase
ELIXIR CORE CUTS ALLOCATIONS ACROSS STRING AND AST OPERATIONS
By RepoJournal · Filed · About Elixir & Phoenix
Thomas Cioppettini landed four performance wins overnight that eliminate unnecessary allocations in List.myers_difference, String case conversion, and Macro tree walkers.
The most immediate win ships in List.myers_difference [1], which removed a length computation that was firing on every call. But the bigger story is String.downcase and String.upcase with :ascii flag [2], which were building one cons cell per input byte only to flatten it back to binary. The fix scans without allocating on the first pass, cutting overhead dramatically on the dominant real-world case: URI schemes and HTTP headers that are already in target case. Macro.prewalk and postwalk get dedicated fast paths [3] that bypass wrapper closures and tuple allocations, preserving exact traversal semantics while cutting per-node overhead. Separately, Range.disjoint?/2 [4] now handles ranges beyond float precision correctly. On the Ecto side, embedded_load and embedded_dump now accept loader/dumper arguments [5], letting custom types like MapOf specify their own format without hardcoding :json.
One email a day. Unsubscribe in one click.
Keep up with Elixir & Phoenix in about 3 minutes a day: what actually shipped — the commits, pull requests, releases, and security advisories that matter.
One email a day. Unsubscribe in one click. Read a past issue →
Action items
- → Pull String performance fixes into your branch if you process headers or URIs at scale elixir-lang/elixir [plan]
- → Review the Macro walker changes if you do AST inspection in compile-time code elixir-lang/elixir [monitor]
- → Evaluate Ecto's new loader/dumper argument if you build custom embedded types elixir-ecto/ecto [monitor]
References
- [1] perf: Remove unused length computation in List.myers_difference (#15753) elixir-lang/elixir
- [2] perf: Avoid intermediate charlist in String.downcase/upcase with :ascii ↗ elixir-lang/elixir
- [3] perf: Add accumulator free fast paths to Macro.prewalk/2 and postwalk/2 ↗ elixir-lang/elixir
- [4] fix: Range.disjoint?/2 for ranges beyond float precision (#15760) elixir-lang/elixir
- [5] Allow loader/dumper be passed through Ecto.embedded_load / Ecto.embedded_dump ↗ elixir-ecto/ecto