0Pricing
Ruby Academy · Урок

Оптимизация памяти

Сокращайте число выделений памяти

«Оптимизация памяти» — бесплатный урок Ruby Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Ruby Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Ruby Academy содержит 4 уроков всего.

Почему важна память

Каждый создаваемый Ruby объект расходует память и увеличивает нагрузку на сборщик мусора. Чем меньше выделений, тем быстрее и компактнее программы.

  • Сборщик мусора приостанавливает выполнение, чтобы освободить объекты
  • Большое количество выделений вызывает более частые запуски сборщика мусора
  • Уменьшение количества выделений часто даёт наибольший выигрыш
before = GC.stat(:total_allocated_objects)
100.times { 'new string' + '!' }
after = GC.stat(:total_allocated_objects)
puts "Allocated: #{after - before} objects"

Подсчёт выделений

GC.stat предоставляет счётчики выделений, разницу которых можно вычислить до и после выполнения блока.

  • :total_allocated_objects постоянно увеличивается
  • Вычтите значение до выполнения из значения после, чтобы измерить отдельный участок
def allocations
  before = GC.stat(:total_allocated_objects)
  yield
  GC.stat(:total_allocated_objects) - before
end

puts allocations { Array.new(1000) { |i| i.to_s } }

Замороженные строковые литералы

Повторяющиеся строковые литералы каждый раз выделяют память под новый объект. Их заморозка позволяет Ruby повторно использовать один неизменяемый экземпляр.

  • Добавьте специальный комментарий в начало файла
  • Или вызовите .freeze для отдельных литералов
# frozen_string_literal: true

s1 = 'hello'
s2 = 'hello'
puts s1.equal?(s2)

Избегайте выделения памяти в циклах

Создание объектов внутри часто выполняемых циклов многократно увеличивает объём выделяемой памяти. Вынесите константы за пределы цикла.

  • Создайте регулярные выражения, массивы и строки один раз
  • Повторно используйте их на каждой итерации
PATTERN = /\d+/

def count_numbers(lines)
  lines.count { |line| line.match?(PATTERN) }
end

puts count_numbers(['a1', 'bb', 'c3'])

Изменяющие методы (с восклицательным знаком)

Методы без восклицательного знака возвращают новые объекты, а методы с восклицательным знаком изменяют объект на месте, экономя память.

  • map!, gsub!, sort!
  • Используйте их только тогда, когда безопасно изменять исходный объект
arr = [3, 1, 2]
arr.sort!
puts arr.inspect

s = 'hello world'
s.upcase!
puts s

Символы и строки в качестве ключей

Символы интернируются: один и тот же символ представлен одним общим объектом. Используйте их в качестве ключей хеша.

  • Строковые ключи каждый раз выделяют память под новую строку
  • Символы экономят память при повторных поисках
puts :name.equal?(:name)
puts 'name'.equal?('name')

Ленивые перечислители

Цепочка из map и select создаёт промежуточные массивы. lazy обрабатывает элементы по одному.

  • Промежуточные коллекции не выделяются
  • Это особенно удобно для больших или бесконечных последовательностей
result = (1..Float::INFINITY).lazy
  .select { |n| n.even? }
  .map { |n| n * n }
  .first(5)
puts result.inspect

Потоковая обработка вместо загрузки

Чтение целого файла в память расточительно. Вместо этого обрабатывайте его потоково, строка за строкой.

  • each_line обрабатывает по одной строке за раз
  • Постоянный объём памяти независимо от размера файла
text = "line1\nline2\nline3"
text.each_line do |line|
  puts line.strip.upcase
end

Объединение строк

Построение строк с помощью + в цикле каждый раз выделяет память под новую строку. Используйте <<, чтобы добавлять данные на месте.

  • + создаёт новый объект
  • << изменяет существующий буфер
buffer = String.new
5.times { |i| buffer << "item#{i} " }
puts buffer

Пулы объектов и повторное использование

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

  • Кэшируйте разобранные конфигурации или скомпилированные регулярные выражения
  • Используйте константу или мемоизированное значение
def config
  @config ||= { host: 'localhost', port: 4567 }
end

puts config.equal?(config)

Вызов сборщика мусора для анализа

Вы можете изучить работу сборщика мусора, чтобы подтвердить улучшения.

  • GC.stat(:count) показывает, сколько раз запускался сборщик мусора
  • Меньшее количество запусков после оптимизации — хороший признак
start = GC.stat(:count)
50_000.times { |i| [i] }
puts "GC runs: #{GC.stat(:count) - start}"

Быстрая проверка

Проверьте свои знания об оптимизации памяти.

Повторение

Вы научились оптимизировать память:

  • Подсчитывать выделения памяти с помощью GC.stat
  • Замораживать строковые литералы и повторно использовать объекты
  • Предпочитать методы с восклицательным знаком и <<, чтобы не создавать новые объекты
  • Использовать символы для ключей и ленивые перечислители для конвейеров
  • Обрабатывать большие объёмы данных потоково вместо полной загрузки

Далее Вы разберёте распространённые узкие места производительности.

Часто задаваемые вопросы

Урок «Оптимизация памяти» бесплатный?

Да — полный текст урока «Оптимизация памяти» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Ruby Academy, подпишись на CoddyKit PRO. Курс Ruby Academy содержит 4 уроков всего.

Чему я научусь в уроке «Оптимизация памяти»?

Сокращайте число выделений памяти Ты практикуешь Ruby Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Ruby Academy?

Предыдущий опыт не требуется. Ruby Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Оптимизация памяти»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Ruby Academy?

Да. Каждый урок Ruby Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Измерение производительности
  2. Инструменты профилирования
  3. Оптимизация памяти
  4. Распространённые узкие места
← Назад к Ruby Academy