elixir_sense icon indicating copy to clipboard operation
elixir_sense copied to clipboard

Simplify all_loaded call

Open josevalim opened this issue 6 months ago • 3 comments

Today it is defined as:

  defp all_loaded do
    timed_log "all loaded", 1 do
      Applications.get_modules_from_applications()
      |> Enum.filter(fn module ->
        try do
          Code.ensure_loaded?(module) and function_exported?(module, :module_info, 0)
        rescue
          _ ->
            false
        end
      end)
    end
  end

Unfortunately, Code.ensure_loaded? is a bit expensive. Luckily, Application.spec(:app_name, :modules) should return correct and up to date information, except for the current app and path dependencies, since "live code compilation" (as done by Phoenix and others) may define new modules and without reload the application spec (which would require the app to stop).

So my suggestion is to improve Applications.get_modules_from_applications() to Application.spec(:app_name, :modules) for all apps, except the current apps and path deps (which you can compute on boot). For those, you do a File.ls(path_to_ebin) and get the beam files. This should actually fix bugs, given if you define a module in a Phoenix app today, it likely won't be picked by Applications.get_modules_from_applications()?

josevalim avatar Aug 17 '25 07:08 josevalim

@josevalim Applications.get_modules_from_applications() calls :application.get_key(app, :modules) which is exactly the same as Application.spec(:app_name, :modules). The code in question loads the modules to find ones implementing a plugin behaviour.

lukaszsamson avatar Aug 20 '25 20:08 lukaszsamson

Yes, I understand that. My comment was not about the get_key/spec part, but about ensure_loaded. This is a very expensive operation and, if it is only needed for plug-ins, then it should likely be called once on boot, but I would strongly suggest to make plugins opt-in on the mix.exs file. :)

josevalim avatar Aug 20 '25 20:08 josevalim

The plugins are mix deps from the client project. Loading them at boot is not possible. One option is doing that after initial mix compile.

lukaszsamson avatar Aug 20 '25 22:08 lukaszsamson