Неявный против явного сбора мусора - PullRequest
0 голосов
/ 07 мая 2018

Фон

Я создал API и выполнил профилирование использования памяти и времени обработки для каждого веб-сервиса, используя это руководство и gem profiler memory .

Я создал таблицу для сохранения всех результатов профилирования следующим образом:

      Request      | Memory Usage(b) | Retained Memory(b) | Runtime(seconds)
----------------------------------------------------------------------------
  Post Login       | 444318          |   35649            | 1.254
  Post Register    | 232071          |   32673            | 0.611
  Get 10 Users     | 11947286        |   2670333          | 3.456
  Get User By ID   | 834953          |   131300           | 0.834

Примечание: все номера являются средним числом вызовов одной и той же услуги 3 раза подряд.

И я прочитал много руководств и ответов (например, это и это ) говорит, что сборщик мусора отвечает за освобождение памяти, и мы не должны явно вмешиваться в управление памятью.

Затем я просто заставил сборщик мусора запускаться после каждого действия (в целях тестирования), добавив следующий фильтр в APIController:

after_action :dispose

def dispose
   GC.start
end

И я обнаружил, что использование памяти сокращается слишком сильно (более чем на 70%), оставшаяся память почти такая же, как и раньше, и время выполнения также уменьшается.

      Request      | Memory Usage(b) | Retained Memory(b) | Runtime(seconds)
----------------------------------------------------------------------------
  Post Login       | 38636           |   34628            | 1.023
  Post Register    | 37746           |   31522            | 0.583
  Get 10 Users     | 2673040         |   2669032          | 2.254
  Get User By ID   | 132281          |   128913           | 0.782

Вопросы:

  1. Полезно ли добавлять такой фильтр и каковы побочные эффекты?
  2. Я думал, что время выполнения будет больше, чем раньше, но, кажется, меньше, в чем может быть причина?

Обновление:

Я использую Ruby 2.3.0 и gc_tracer gem для мониторинга состояния кучи, потому что боюсь, что старые проблемы с сборкой мусора выделены в Ruby 2.0 и 2.1

Проблема в том, что Ruby GC запускается на общем количестве объектов, а не общий объем используемой памяти

Затем, чтобы провести стресс-тест, я запускаю следующее:

while true
  "a" * (1024 ** 2)
end

и в результате этого использование памяти не превышает следующих пределов ( было превышено ранее и GC не будет запускаться ):

RUBY_GC_MALLOC_LIMIT_MAX
RUBY_GC_OLDMALLOC_LIMIT_MAX

Так что теперь я почти уверен, что те же самые GC проблемы 2.0 и 2.1 больше не существуют в 2.3, но все же получают следующие положительные результаты, добавив вышеупомянутый фильтр (after_action :dispose):

  • Объем памяти кучи увеличен на 5% до 10% ( проверьте этот связанный вопрос )
  • Общее время выполнения увеличено на 20% до 40% (тест выполнен с использованием стороннего инструмента Почтальон , который использует мой API)

Я все еще ищу ответы на два моих вопроса выше.

Любая обратная связь будет принята с благодарностью

...