-
Notifications
You must be signed in to change notification settings - Fork 529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slow compile times in a large app due to full schema recompilation since upgrading from 1.4 #1038
Comments
Hi @dmarkow, can you try using the persistent term backend found here: https://hexdocs.pm/absinthe/1.5.5/Absinthe.Schema.PersistentTerm.html ? |
@benwilson512 Big improvement! I initially tried that but it didn't seem to improve anything. But I just looked at the implementation and noticed that calling |
See absinthe-graphql#1038 -- `@schema_provider Absinthe.Schema.PersistentTerm` needs to be added after the `use Absinthe.Schema` line.
See #1038 -- `@schema_provider Absinthe.Schema.PersistentTerm` needs to be added after the `use Absinthe.Schema` line.
@dmarkow we will continue to work on improving compilation performance. Notably although 1.5 and 1.6 are slower to compile, they actually perform at run time much better and in particular when using persistent term, use a lot less memory. We'll continue to put effort into improving compilation speed though, and in a release soon we plan to make the persistent term backend standard. |
Awesome! Thanks for helping me out with this so quickly. |
@benwilson512 One extra piece of info in case it's useful for future work on this. It seems that with PersistentTerm compilation of schema.ex is actually very close that that of 1.4.16. The thing that's delaying it is a 3-second "group pass check" on the project's modules, regardless of using PersistentTerm or not. In 1.4.16, the group pass check took less than a second for the same number of modules.
|
@dmarkow interesting! Can you elaborate a bit on what the "Group pass check" is? This isn't a term I recognize. |
I saw this mentioned in José's post at https://dashbit.co/blog/how-to-debug-elixir-erlang-compiler-performance — from reading through this it sounds like a standard part of Elixir's compilation process, stating that it's "the time to execute a group pass which looks at all modules at once, in order to find undefined functions, emit deprecations, etc." You can track it when you compile with the Relevant code in Elixir for checking the modules:
I tried a dev build of Elixir 1.12 which has some compiler improvements that speed this up quite a bit (reducing that group pass check from around 3 seconds to 1 second) so it may not need to be something to worry about on Absinthe's end. In the mean time, it also seems that splitting some of my larger absinthe schema type files into multiple smaller files helps take advantage of the parallel checking a bit more and shaves a second off even under Elixir 1.11. So with a combination of PersistentTerm, splitting my larger schema files, and using Elixir 1.12, I'm back in the 700-800ms zone for the group pass check, and a total of around 3 seconds of real world time (which feel instantaneous compared to the 15-20 seconds I started with) 🎉 |
OK great, glad we could get things back to a good place! |
I have a fairly large API using Absinthe (25,000 lines of code, around 400 objects, 300 queries, and 300 mutations). I've noticed that it's getting slower and slower to compile my schema, and since just about every module in my app is reachable from one of my resolvers, touching basically any file in the project results in a full recompile of my schema, even if none of my fields/queries changed. Compiling the schema adds around 15 seconds to every recompilation, making frequent updates and test runs painful.
I spent some time digging through and determined that most of the time is spent in phase/schema/compile.ex, specifically at the
Module.create(...)
call, which takes around 10 seconds to generate theApiWeb.Schema.Compiled
module.It seems to make no difference if I keep everything in one giant schema file versus splitting it by my contexts and using import_types/import_fields. I found https://devonestes.herokuapp.com/trying-to-speed-up-compilation-with-absinthe but even trying the umbrella app experiment outlined there, my compile times only improved about 10% (and added a lot of complexity).
Out of curiosity I reverted back to absinthe 1.4.16 and everything is way faster. The
schema.ex
file is still recompiled, but it happens in around 750ms instead of 15 seconds. The bump up to 1.5 is where the recompilation issues started.Is this just a downside to the convenience of the new features added since 1.5, or is there something that can be done either on Absinthe's end or my own to help with this?
Environment
Expected behavior
Changes that don't actually affect my schema to not trigger a costly recompile.
Actual behavior
Touching any file referenced by a resolver triggers a complete recompile of my schema.
Relevant Schema/Middleware Code
Basic schema with many fields, queries, and mutations. No extra plugins/middleware.
The text was updated successfully, but these errors were encountered: