|
|
|
@ -7,9 +7,9 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
`c:Indexer.Memory.Shrinkable.shrink/0`. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
require Bitwise |
|
|
|
|
require Logger |
|
|
|
|
|
|
|
|
|
import Bitwise |
|
|
|
|
import Indexer.Logger, only: [process: 1] |
|
|
|
|
|
|
|
|
|
alias Indexer.Memory.Shrinkable |
|
|
|
@ -47,7 +47,7 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
|
|
|
|
|
@impl GenServer |
|
|
|
|
def init(options) when is_map(options) do |
|
|
|
|
state = struct!(__MODULE__, options) |
|
|
|
|
state = struct!(__MODULE__, Map.put_new(options, :limit, define_memory_limit())) |
|
|
|
|
{:ok, timer_reference} = :timer.send_interval(state.timer_interval, :check) |
|
|
|
|
|
|
|
|
|
{:ok, %__MODULE__{state | timer_reference: timer_reference}} |
|
|
|
@ -66,14 +66,14 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
@impl GenServer |
|
|
|
|
def handle_info(:check, state) do |
|
|
|
|
def handle_info(:check, %{limit: limit} = state) do |
|
|
|
|
total = :erlang.memory(:total) |
|
|
|
|
|
|
|
|
|
set_metrics(state) |
|
|
|
|
|
|
|
|
|
shrunk_state = |
|
|
|
|
if memory_limit() < total do |
|
|
|
|
log_memory(%{limit: memory_limit(), total: total}) |
|
|
|
|
if limit < total do |
|
|
|
|
log_memory(%{limit: limit, total: total}) |
|
|
|
|
shrink_or_log(state) |
|
|
|
|
%{state | shrunk?: true} |
|
|
|
|
else |
|
|
|
@ -81,8 +81,8 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
final_state = |
|
|
|
|
if state.shrunk? and total <= memory_limit() * @expandable_memory_coefficient do |
|
|
|
|
log_expandable_memory(%{limit: memory_limit(), total: total}) |
|
|
|
|
if state.shrunk? and total <= limit * @expandable_memory_coefficient do |
|
|
|
|
log_expandable_memory(%{limit: limit, total: total}) |
|
|
|
|
expand(state) |
|
|
|
|
%{state | shrunk?: false} |
|
|
|
|
else |
|
|
|
@ -94,6 +94,28 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
{:noreply, final_state} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp define_memory_limit do |
|
|
|
|
case Application.get_env(:indexer, :memory_limit) do |
|
|
|
|
integer when is_integer(integer) -> integer |
|
|
|
|
_not_set -> memory_limit_from_system() |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp memory_limit_from_system do |
|
|
|
|
default_limit = 1 <<< 30 |
|
|
|
|
|
|
|
|
|
percentage = |
|
|
|
|
case Application.get_env(:explorer, :mode) do |
|
|
|
|
:indexer -> 100 |
|
|
|
|
:all -> Application.get_env(:indexer, :system_memory_percentage) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
case :memsup.get_system_memory_data()[:total_memory] do |
|
|
|
|
nil -> default_limit |
|
|
|
|
total_memory -> floor(total_memory * percentage / 100) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp flush(message) do |
|
|
|
|
receive do |
|
|
|
|
^message -> flush(message) |
|
|
|
@ -250,8 +272,4 @@ defmodule Indexer.Memory.Monitor do |
|
|
|
|
|> Enum.map(fn pid -> {pid, memory(pid)} end) |
|
|
|
|
|> Enum.sort_by(&elem(&1, 1), &>=/2) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp memory_limit do |
|
|
|
|
Application.get_env(:indexer, :memory_limit) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|