zachdaniel

zachdaniel

Creator of Ash

Hey folks, made some recent performance improvements to spark, the tool underlying all of our DSLs. GitHub - ash-project/spark: Tooling for building DSLs in Elixir · GitHub

It should make code that accesses DSL options significantly faster. If people can try it out with mix deps.update spark that would be great :slight_smile: Bonus points to anyone who has some level of performance measuring, if you could show how its impacted things for you, that would be great :heart:

Some technical context around what was actually done:

Modules that use the DSL built by spark create a data structure under the hood, that looks like this:

%{
  persisted: %{...explicitly cached things that are used often},
  [:attributes] => %{entities: [...], options: [...]},
  [:json_api, :routes] => %{entities: [...], options: [...]},
  ... and so on
}

This data structure groups everything by section. However, when accessing DSL information, you always go through a set of functions provided by spark, for example Spark.Dsl.Extension.get_opt and Spark.Dsl.entities. We did this on purpose to allow us to optimize the underlying storage mechanisms and access patterns. While doing some recent benchmarking, we saw that the current naive implementations were taking quite a bit of time during the execution of Ash actions. The implementation would be something like dsl |> Map.get(path) |> Map.get(:options) |> Keyword.get(option_name). We would do similar things with entities.

What we’ve instead done is defined functions under the hood for each section path and option, that pattern matches and returns the value. It looks like this:

        for {path, %{opts: opts}} <- @spark_dsl_config, is_list(path) do
          for {key, value} <- opts do
            def fetch_opt(unquote(path), unquote(key)) do
              {:ok, unquote(Macro.escape(value))}
            end
          end
        end

        def fetch_opt(_, _), do: :error

Then we updated Extension.get_opt to call this generated function instead of getting the big DSL map and pulling out values. Measurements so far show significant performance improvements (especially in bulk creates, which s what sparked this recent investigation into unnecessary slowness).

Aside from this, we also leveraged the persist key to optimize a bunch of commonly accessed Ash DSL items.

Please give it a try! Bonus points to anyone who has some level of performance measuring, if you could show how its impacted things for you, that would be great :heart:

Showing Posts 2 to 1

jimsynz

jimsynz

Ash Core Team

Woah. That’s epic.

frankdugan3

frankdugan3

I have an ERP app (82,528 lines of Elixir) with over 80 resources that heavily leverage Ash extensions, and it seems like these improvements also vastly improve compile time, cutting it down to less than half for me!

With spark 1.1.46:

hsm on  graphql-api-tokens [!?] via  v1.14.5 (OTP 25) mix compile --force
Compiling 499 files (.ex)
Generated hsm app
Compiling golang module :gopcua_bridge (native/gopcua_bridge)...
hsm on  graphql-api-tokens [!?] via  v1.14.5 (OTP 25) took 1m26s

With spark 1.1.48:

hsm on  graphql-api-tokens [!?] via  v1.14.5 (OTP 25)

ᕕ(ᐛ)ᕗ mix compile --force
Compiling 499 files (.ex)
Generated hsm app
Compiling golang module :gopcua_bridge (native/gopcua_bridge)...
hsm on  graphql-api-tokens [!?] via  v1.14.5 (OTP 25) took 41s
15
Post #1
— All posts loaded —

Where Next? Top

Trending in News & Updates Top

Jskalc
LiveVue v1.0 released After four release candidates and a lot of community feedback, LiveVue 1.0 is stable :tada: I’ve built a dedicated...
New
webofbits
Cairn is a small OTP library for message delivery, lightweight function processes, supervised work, and waiting on results. The goal is ...
New
woylie
<span class="hashtag-icon-placeholder"></span>let-me 3.0.4 has been released. Changed Log the policy module and the check module in the...
New
webofbits
Aludel 0.8.0 is now available on GitHub and Hex. This release adds typed_judge assertions for evaluations that need deterministic, struc...
New
woylie
Flop Phoenix 0.27.0 has been released. Changed Require Flop 0.29.0, which turns Flop.Schema from a protocol into a behaviour. Determin...
New
woylie
Flop 0.29.0 has been released. Added Add Flop.allowed_fields/2, which returns the fields that may be filtered or sorted for the given ...
New
woylie
Doggo 0.16.1 has been released. Changed The expanded attribute of the tree_item is now handled as initial state only and cannot be upd...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews