Управление памятью с помощью NSDecimalNumber: Как избежать проблем с памятью в тесных циклах? - PullRequest
0 голосов
/ 26 августа 2009

У меня плотный цикл, который повторяется около 500 раз. На каждой итерации будет создаваться несколько объектов NSDecimalNumber для выполнения арифметики.

Пример - этот фрагмент кода находится в цикле for. -decimalNumberByAdding: метод создает новый экземпляр NSDecimalNumber и автоматически выпускает его.

resultDecimalNumber = [resultDecimalNumber decimalNumberByAdding:anotherDecimalNumber];

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

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

Представь, что это был мой цикл:

for(i=0, i<500, i++) {
    resultDecimalNumber = [resultDecimalNumber decimalNumberByAdding:anotherDecimalNumber];
}

Что бы я там добавил? Должен ли я создать пул автозапуска внутри цикла и слить его? Будет ли это иметь смысл?

Ответы [ 3 ]

3 голосов
/ 26 августа 2009

Используйте C struct NSDecimal. Из Apple "Темы программирования чисел и значений для какао" :

Вы можете рассмотреть интерфейс C, если вам не нужно обрабатывать десятичную числа как объекты, то есть если вы не нужно хранить их в объектно-ориентированная коллекция, как экземпляр NSArray или NSDictionary. Вы также можете рассмотреть C интерфейс, если вам нужно максимум эффективность. Интерфейс C быстрее и использует меньше памяти, чем NSDecimalNumber класс.

Если вам нужна изменчивость, вы можете объединить два интерфейса. использование функции из интерфейса C и преобразовать свои результаты в экземпляры NSDecimalNumber.

Я использую NSDecimal, а не NSDecimalNumber, на iPhone именно по этой причине. Вы получаете всю точность NSDecimalNumber с гораздо меньшими накладными расходами.

Сравнение двух на моем Mac (MacBook Air, 2-го поколения) дает следующие результаты:

NSDecimal
Additions per second: 3355476.75
Subtractions per second: 3866671.27
Multiplications per second: 3458770.51
Divisions per second: 276242.32

NSDecimalNumber
Additions per second: 676901.32
Subtractions per second: 671474.6
Multiplications per second: 720310.63
Divisions per second: 190249.33

Даже игнорируя использование памяти, вы получаете почти пятикратное ускорение в каждой операции, кроме деления, если вы используете NSDecimal и API C.

1 голос
/ 26 августа 2009

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

0 голосов
/ 26 августа 2009

Вы можете получить встроенные эквиваленты с плавающей точкой для NSDecimalNumber s, которые вы используете, а затем преобразовать результат обратно в NSDecimalNumber в конце цикла:

double total(0);

for (i = 0; i < 500; ++i)
{
    total += [anotherDecimalNumber doubleValue];
}

resultDecimalNumber = // turn total back into an NSDecimalNumber

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

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