Почему при каждом запуске пустых рельсов каждый раз, когда он запускается, имеет разный объем памяти?

Мы пытались выяснить, как уменьшить загрузочный объем памяти нашего приложения rails, идентифицировав головоломки памяти и найдя альтернативы или решения.

Но есть одно поведение в OS X, которое я нахожу озадаченным.

С новым созданным рельсом (rails new memoryusage), без Gemfile, без моделей, без данных и без транзакций при запуске rails c отображает OSX-память для соответствующего процесса ruby, каждый раз, когда он начиная с 60 МБ до 65 МБ, без заметного шаблона относительно того, почему одно и то же приложение может требовать меньше или больше памяти за выполнение.

Я предполагаю, что это должно каким-то образом повлиять на то, как Ruby выделяет память, но я не совсем понимаю, почему распределение памяти будет настолько диким для одного и того же кода и без обработки переменных.

Мы имеем аналогичное непредсказуемое поведение, когда пытаемся вычислить память, потребляемую процессом, после того, как требуется каждый камень в Gemfile. Мы загружаем процесс ванильных рельсов, затем в rails c запускаем script, который анализирует Gemfile и требует каждого Gem индивидуально, регистрируя память до и после запроса, и мы замечаем, что не только память след не имеет согласованной начальной точки, но и инкрементные "шаги" в нашем потреблении памяти сильно различаются.

Мы загрузили наш процесс три раза один за другим и измерили начальную память и инкрементную память, необходимую для каждого драгоценного камня. Мало того, что следы памяти загрузочной книги отскакивают между 60 МБ и 92 МБ, но точки, в которых мы видели скачки памяти при загрузке каждого драгоценного камня, были непоследовательными - иногда загрузка SASS съедала еще 5 МБ, иногда это не будет, иногда active_merchant потребует дополнительно 10 МБ, другие - нет.

                    :    BOOT UP #1            :    BOOT UP #2            :    BOOT UP #3           
gem                 :  increment |      total  :  increment |      total  :  increment |      total
rails               :       0.00 |      59.71  :       0.00 |      92.54  :       0.18 |      67.76
unicorn             :       0.52 |      60.24  :       0.52 |      93.06  :       3.35 |      71.12
haml                :       8.77 |      69.02  :       1.88 |      94.94  :       9.45 |      80.57
haml-rails          :       0.00 |      69.02  :       0.00 |      94.94  :       0.00 |      80.57
sass                :       4.36 |      73.38  :       6.95 |     101.89  :       0.99 |      81.55
mongoid             :       0.00 |      73.38  :       0.00 |     101.89  :       0.00 |      81.55
compass             :      11.56 |      84.93  :       3.23 |     105.12  :       8.41 |      89.96
compass-rails       :       0.00 |      84.93  :       0.08 |     105.20  :       0.00 |      89.96
compass_twitter_bootstrap:       0.00 |      84.93  :       0.00 |     105.20  :       0.00 |      89.96
profanalyzer        :       0.59 |      85.52  :       0.46 |     105.66  :       0.64 |      90.60
simple_form         :       0.34 |      85.87  :       0.35 |     106.01  :       0.00 |      90.60
sorcery             :       0.00 |      85.87  :       0.25 |     106.26  :       1.07 |      91.67
validates_timeliness:       1.47 |      87.34  :       1.82 |     108.07  :       1.62 |      93.29
mongoid_token       :       0.00 |      87.34  :       0.00 |     108.07  :       0.00 |      93.29
nested_form         :       0.00 |      87.34  :       0.00 |     108.07  :       0.01 |      93.30
nokogiri            :       0.86 |      88.20  :       1.16 |     109.24  :       1.37 |      94.67
carmen              :       0.00 |      88.20  :       0.07 |     109.30  :       0.00 |      94.67
carrierwave/mongoid :       2.78 |      90.98  :       0.38 |     109.69  :       0.13 |      94.80
yajl                :       0.04 |      91.02  :       0.04 |     109.73  :       0.04 |      94.84
multi_json          :       0.00 |      91.02  :       0.00 |     109.73  :       0.00 |      94.84
uuid                :       0.00 |      91.03  :       0.00 |     109.73  :       0.41 |      95.25
tilt                :       0.00 |      91.03  :       0.00 |     109.73  :       0.00 |      95.25
dynamic_form        :       0.00 |      91.04  :       0.00 |     109.73  :       0.00 |      95.25
forem               :       0.03 |      91.07  :       0.00 |     109.73  :       0.00 |      95.25
browser             :       0.00 |      91.07  :       0.00 |     109.73  :       0.00 |      95.25
activemerchant      :       2.17 |      93.24  :       1.18 |     110.92  :      10.58 |     105.83
kaminari            :       0.00 |      93.24  :       0.00 |     110.92  :       0.00 |     105.83
merit               :       0.00 |      93.24  :       0.00 |     110.92  :       0.00 |     105.83
memcachier          :       0.00 |      93.24  :       0.00 |     110.92  :       0.00 |     105.83
dalli               :       0.01 |      93.25  :       0.05 |     110.96  :       0.34 |     106.17
bitly               :       2.47 |      95.72  :       9.43 |     120.40  :       1.53 |     107.70
em-synchrony        :       1.00 |      96.72  :       0.18 |     120.57  :       0.55 |     108.24
em-http-request     :       5.56 |     102.28  :       2.15 |     122.72  :       1.40 |     109.64
httparty            :       0.00 |     102.28  :       0.00 |     122.72  :       0.00 |     109.64
rack-block          :       0.00 |     102.28  :       0.00 |     122.72  :       0.00 |     109.64
resque/server       :       1.21 |     103.49  :       1.73 |     124.45  :       1.68 |     111.32
resque_mailer       :       0.00 |     103.49  :       0.00 |     124.45  :       0.00 |     111.32
rack-timeout        :       0.00 |     103.49  :       0.00 |     124.45  :       0.00 |     111.32
chronic             :       1.66 |     105.15  :       0.67 |     125.12  :       0.64 |     111.96
oink                :       0.00 |     105.15  :       0.00 |     125.12  :       0.00 |     111.96
dotenv-rails        :       0.00 |     105.15  :       0.00 |     125.12  :       0.00 |     111.96
jquery-rails        :       0.00 |     105.15  :       0.03 |     125.15  :       0.00 |     111.96
jquery-ui-rails     :       0.00 |     105.15  :       0.00 |     125.15  :       0.00 |     111.96

Мне ясно, что есть что-то очень основное, что мне не хватает, и я не понимаю, как память распределена для процессов Ruby, но мне трудно понять, почему это может быть похоже на кажущееся стохастическое. У кого-нибудь есть мысли?

Ответ 1

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

OS X получила все большую поддержку ASLR, начиная с 10.5, и с 10.8 даже ядро ​​случайно перемещается.

В некоторых случаях ASLR может привести к тому, что сегмент программы будет использовать дополнительные страницы в зависимости от того, пересечет ли смещение границы страницы. Поскольку существует много сегментов и много библиотек, этот эффект трудно предсказать.

Мне также интересно, если (учитывая огромные различия, которые вы видите), возможно, это проблема с сообщением в OS X. Интересно, несется ли накладные расходы для общих объектов несправедливо в зависимости от порядка загрузки.

Вы можете проверить это, обратившись к этому вопросу о переполнении стека: Отключение ASLR в Mac OS X Snow Leopard.