Как NSMutableData выделяет память? - PullRequest
4 голосов
/ 02 августа 2010

Когда я запускаю следующий код, он медленно загружает мою память и даже начинает использовать swap:

 long long length = 1024ull * 1024ull * 1024ull * 2ull; // 2 GB

 db = [NSMutableData dataWithLength:length];

 char *array = [db mutableBytes];

 for(long long i = 0; i < length - 1; i++) {
      array[i] = i % 256;
 }

Если я запускаю его без цикла for, память вообще не используется:

 long long length = 1024ull * 1024ull * 1024ull * 2ull;
 db = [NSMutableData dataWithLength:length];
 char *array = [db mutableBytes];
 /* for(long long i = 0; i < length - 1; i++) {
      array[i] = i % 256;
 } */

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

Это делается через аппаратное обеспечение (ЦП)?

Есть ли способ для NSMutableData перехватывать записи в память в своей «зарезервированной» памяти и только затем делать «выделение»?

Означает ли это также, что вызов [NSMutableData dataWithLength:length] никогда не сможетпотерпеть поражение?Может ли он выделить какой-либо размер памяти, используя swap, чтобы получить его, если это необходимо?

Если это не удастся, будет ли моя переменная db нулевой?

В «Ссылке на класс NSMutableData» от Apple я видел только расплывчатопредложения по этим темам.

1 Ответ

6 голосов
/ 02 августа 2010

Это не столько проблема NSMutableData, сколько проблема ядра / ОС. Если процесс запрашивает (большой) кусок памяти, ядро, как правило, просто скажет: «все в порядке, поехали». Но только при фактическом использовании он действительно («физически») выделяется. Это нормально, поскольку если ваша программа запускается с malloc 2 ГБ (как вы делаете здесь), в противном случае она мгновенно вытеснит другие программы для замены, хотя на практике вы часто не сразу используете 2 ГБ.

При доступе к странице памяти, которая фактически отсутствует в физической памяти, ядро ​​получит сигнал от ЦП. Если страница должна быть там (потому что она находится в пределах вашего блока размером 2 ГБ), она будет помещена на место (возможно, из раздела подкачки), и вы даже не заметите. Если страницы не должно быть (поскольку адрес не выделен в вашей виртуальной памяти), вы получите ошибку сегментации (ошибка типа SIGSEGV или EXC_BAD_ACCESS).

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

В Интернете много страниц, объясняющих это лучше и более подробно; Я просто хотел дать краткое вступление, чтобы у вас были условия для Google.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...