Background I was recently working on a project that invoked `System.get_env/0` on every request it handled. Someone changed the infrastructure the application was deployed on and greatly increased the number of environment variables (3x more) in the environment the Elixir application ran in, and the performance of the application degraded by about that same amount (3x slower than before). When I profiled the application I quickly found that most of the request handling was spent waiting for the `System.get_env/0` function to return. I changed the code so `System.get_env/0` was only invoked on startup and the performance issue was resolved.
Problem When I was working on the performance issue in the app the flame graphs revealed something interesting - Erlang was actually formatting the environment variables from a proplist to a list of strings in certain format, and then Elixir was undoing the formatting by parsing the strings back to a map! Because of this the performance of the `System.get_env/0` function call is tied to the number of variables in the environment. - The Erlang code that formats the variables: https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl#L118 - The Elixir code that parses them and puts them in a dictionary: https://github.com/elixir-lang/elixir/blob/v1.10.3/lib/elixir/lib/system.ex#L438 Possible Solutions *1. Update the `System.get_env/0` function to use `os:list_env_vars/0` function* This function already exists returns a proplists in the format `{VariableName, VariableValue}`. All we need to do is replace the existing code with def get_env do Enum.into(:os.list_env_vars(), %{}) end This would solve the performance issue and simplify the Elixir code! The downside is that `os:list_env_vars/0` is not a documented function, which I assume means it's not recommended for other applications to rely on it. *2. Wait for Erlang to change* Because I assumed `os:list_env_vars/0` is not a function that Elixir should be relying on (although nothing prevents it from doing so), I have created an enhancement ticket on the Erlang issue tracker to document `os:list_env_vars/0` or implement another function that returns the environment variables in a proplist with `{VariableName, VariableValue}` tuples - https://bugs.erlang.org/browse/ERL-1332. <https://bugs.erlang.org/browse/ERL-1332> Once Erlang implements a documented function that does this we could then begin updating Elixir. Thoughts? I doubt this is something that is run into very often but it could be easily improved. -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/0aecb090-2cbb-46af-8ff4-e34337b123d4o%40googlegroups.com.