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

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

В этой статье я постараюсь дать вам базовое представление о памяти и объяснить, почему это так просто - покажу то, чего большинство из вас раньше не видели.

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

Воображение

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

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

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

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

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

Вес

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

Вернемся к самому маленькому объекту памяти - байту. Кто-то мог подумать: «Но Бит меньше Байта, он глуп?». Ты на 100% прав, то есть насчет Бита, я не идиот, который бы тебе лгал. Тогда почему я сказал это?

Давайте разберемся с этим немного теории.

Один байт состоит из 8 бит. Итак, бит меньше байта.

Еще вам нужно знать, что Bit может иметь только два значения: 1 или 0. Причина очевидна - у нашего «компьютера» невероятное количество «огней». Каждый свет может иметь сигнал пройден или нет. В физическом смысле наш Бит в памяти - это единственный Свет в компьютерной системе. Если сообщение передано, то в битовом слоте стоит 1, и индикатор горит, если нет, то 0 и индикатор не горит.

Если 1 байт = 8 бит и каждый бит может иметь значение 0 или 1, используя комбинаторику, мы можем вычислить, сколько различных значений может быть сохранено в нем.

Он может иметь два значения в каждом доступном слоте - 0 или 1, а их восемь.

2?2?2?2?2?2?2?2

? - это оператор, который следует использовать.

Поскольку правило между ними - ИЛИ (первый слот 1 ИЛИ 0, второй может быть 1 ИЛИ 0…), нам нужно использовать умножение.

2⁸ = 256.

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

В любом случае, давайте оставим теорию. Почему тогда Байт - это наименьший слот памяти, а не Бит.

Это потому, что минимально возможное выделение (объект, который может храниться в памяти) имеет размер 1 байт, это char.

Подождите минуту. А как насчет логического?

Он может иметь значение «истина» или «ложь», 0 или 1. Это эквивалент бита, что означает, что бит должен быть наименьшим слотом распределения памяти.

И вы были бы правы в идеальном мире, но в реальном, логическое значение также занимает 1 байт, что означает, что используется один бит, а еще семь - мусор - сделайте это так, чтобы снизить сложность чтения и записи объектов в объем памяти. Подробнее об этом позже.

Вот несколько увлекательных историй о логических значениях в прошлом.

‹В начале 2000-х у нас был минимальный объем памяти, особенно если вы писали софт для некоторых устройств с малым объемом памяти. В то время разработчики были вынуждены написать специальное переопределение, в котором говорилось, что «логическое значение имеет только 1 бит». Это было пустой тратой времени на разработку и добавило общей сложности. При текущих ресурсах устройства вполне возможно не думать о нескольких потерянных битах, поскольку это ничто с точки зрения общего объема памяти. ›

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

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

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

Теперь, если бы мы сказали нашему «считывателю памяти» прочитать каждый бит объекта и сказать мне, какое значение? Или прочитайте каждый байт объекта и скажите мне, что это за значение? Второй будет в восемь раз быстрее, чтобы подготовить объект размером больше 1 байта. Сравнивая, что логическое значение не так широко используется, было решено, что потеря 7 битов сделает эту операцию более быстрой.

В конце концов, система способна читать каждый слот размером в один байт. Но так ли это?

Ответ будет: «Нет». Байтовое чтение также не является самым быстрым решением для этой операции. По сравнению с объектами, которые в основном используются в приложениях, и с наиболее оптимальной экономией времени на потерю памяти, лучшим решением будет 4 байта. Запомните это число, так как в следующей части, посвященной указателям, вы поймете, почему оно так важно и используется.

Система берет четыре байта за один раз.

Возникает логический вопрос: «Что, если у меня есть символ в моем слоте, а следующий справа слот занимает четыре байта - например, место, где хранится целое число? Как это будет работать, если система захватит первые четыре (один из символов и 3 из Integer), а затем захватит еще четыре (1 из Integer, а остальные - мусор)? ».

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

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

Имейте в виду, что все, что кажется сложным, требует более подробного объяснения. Надеюсь, то, что я написал, сделает вашу жизнь немного проще и даст ответы на вопрос, почему так важно знать структуру памяти. Чтобы понять память - думайте как память =)

В следующей статье я объясню указатели, ссылки, битовые маски, стек и кучу - просто все механизмы, которые работают со структурой памяти, и почему они так выглядят.

Продолжение следует!