Dealing with files with size measurable in hundreds of MB on the BEAM requires some extra care.
This talk aims at covering techniques to implement, profile and troubleshoot scenarios involving large files with a focus on performance and reliability.
omitted for brevity def read(file_name) do GenServer.call(__MODULE__, {:read, file_name}) end def handle_call({:read, file_name}, _from, base_path) do full_path = Path.join(base_path, file_name) contents = File.read!(full_path) {:reply, contents, base_path} end end Claudio Ortolina - ElixirConf EU 2020
reference counted • The cache server reads the content (holding a reference) but not much else • The runtime doesn't trigger a GC Claudio Ortolina - ElixirConf EU 2020
:hibernate}. 2. Don't read in the process, read in the caller (e.g. returning the complete path instead of the file contents) Claudio Ortolina - ElixirConf EU 2020
<- get(url) do File.write!(file_name, data) end end defp get(url) do :httpc.request(:get, {String.to_charlist(url), []}, [], []) |> case do {:ok, result} -> {{_, 200, _}, _headers, body} = result {:ok, body} error -> error end end end Claudio Ortolina - ElixirConf EU 2020
skip the intermediary process that gives access to the file • If we perform a lot of write operations concurrently, raw mode can be faster Claudio Ortolina - ElixirConf EU 2020
Control amount of processes that can use system resources (see duomark/epocxy for some patterns) 3. Perform Soak testing Claudio Ortolina - ElixirConf EU 2020
pitfalls of the BEAM in production • recon: the diagnostics library used in the examples • telemetry packages: telemetry and related projects on Hex Claudio Ortolina - ElixirConf EU 2020