Подтвердить что ты не робот

Быстрая управляющая память

Этот вопрос был очищен, и важная информация переместилась в ответ ниже.


У меня есть некоторые вопросы об управлении памятью.

Я создаю приложение для редактирования фотографий. Поэтому важно поддерживать низкий уровень использования памяти. Также я не буду публиковать код, потому что у меня нет большой утечки памяти при выполнении одной конкретной вещи. Я просто теряю пару килобайт/МБ со всем, что происходит. И переходить десятки тысяч строк кода, чтобы найти килобайты, не забавно;)

мое приложение использует основные данные, множество материалов cifilter, местоположение и основы.

Мое первое представление - это просто табличное представление, которое стоит мне около 5 МБ памяти. Затем вы делаете несколько фотографий, применяете некоторые фильтры, это сохраняется в основных данных, а затем вы возвращаетесь к этому первому виду.

Можно ли действительно избавиться от всего в памяти, кроме данных, необходимых для вождения этого первого вида. (это очень экономичное и удивительное 5mb)

Или всегда будет что-то позади, даже если вы установите все на нуль?


Бонусный вопрос: есть ли разница в размере файла /cpu между UIImageJPEGRepresentation и UIImagePNGRepresentation? Я знаю, что вы можете установить качество сжатия с помощью метода JPEG (сложнее на CPU/gpu?).

Просто пытайтесь уменьшить давление памяти всеми возможными способами.


Update:

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

Проблемы, которые у меня возникали в какой-то момент, были следующими:

  • В некоторых случаях использование пиковой памяти слишком велико.
  • Переход на второй диспетчер представлений и обратно вызывает утечку
  • Редактирование изображения приводит к утечке памяти.
  • Применение фильтра к более чем 4-5 изображениям приводит к сбою из-за низкой памяти, в этот момент утечек памяти больше не было. (проверено в инструментах)

P.s все это было протестировано на iPhone 4, а не на симуляторе.

Здесь был мем, чтобы немного облегчить настроение на этом сайте.

4b9b3361

Ответ 1

Этот вопрос был открыт достаточно долго, и теперь я чувствую себя достаточно уверенно, чтобы ответить на него.


Различные уровни MM:

Аппаратная память

В Swift с ARC мы не можем очистить фактический аппаратный баран. Мы можем сделать так, чтобы ОС могла это сделать для нас. Одна часть использует правильный код (optionals и weak), другая часть создает время для выполнения этой задачи ОС.

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

Этот "аппаратный" утечек памяти вызван тем, что функция всегда принимает следующий доступный слот памяти.

ОС не вступает в "фактическую очистку памяти", потому что нет времени простоя. Установка задержки между каждым проходом полностью исправляет это.


Значения по умолчанию MM

Кастинг

Некоторые операции не влияют на память, другие делают:

let myInt : Int = 1
Float(myInt) // this creates a new instance

Вместо этого попробуйте выполнить кастинг:

(myInt as Float) // this will not create a new instance.

Типы ссылок и типы значений | Классы vs Структуры

Оба имеют свои преимущества и свои опасности.

Структуры являются интенсивными, поскольку они Типы значений. Это означает, что они копируют их значения при назначении другому экземпляру, эффективно удваивая использование памяти. Для этого нет никаких проблем. Это то, что делает Structs Structs.

Классы не имеют такого поведения, поскольку они Reference Types. Они не копируются при назначении. Вместо этого они создают другую ссылку для того же объекта. ARC или Автоматический подсчет ссылок - это то, что отслеживает эти ссылки. У каждого объекта есть счетчик ссылок. Каждый раз, когда вы его назначаете, он увеличивается на один. Каждый раз, когда вы устанавливаете ссылку на nil, закрывающая функция заканчивается или включающий объект Deinits, счетчик уменьшается.

Когда счетчик обращается к 0, объект деинициализируется.

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

Хорошее объяснение слабости

class MyClass {

    var otherClass : MyOtherClass?

    deinit {
        print("deinit") // never gets called
    }
}

class MyOtherClass {

    var myclass : MyClass?

    deinit {
        print("deinit") // never gets called
    }
}

var classA : MyClass? = MyClass()

// sorry about the force unwrapping, don't do it like this
classA!.otherClass = MyOtherClass()
classA!.otherClass!.myclass = classA // this looks silly but in some form this happens a lot

classA = nil
// neither the MyClass nor the MyOtherClass deinitialised and we no longer have a reference we can acces. Immortalitiy reached they have.

установите одну ссылку на weak

class MyOtherClass {

    weak var myclass : MyClass?

    deinit {
        print("deinit") // gets called
    }
}

INOUT

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

Это также хороший способ иметь несколько возвращаемых значений без использования кортежей.

var myInt : Int = 0

// return with inout
func inoutTest(inout number: Int) {

    number += 5

}

inoutTest(&myInt)
print(myInt) // prints 5

// basic function with return creates a new instance which takes up it own memory space
func addTest(number:Int) -> Int {

    return number + 5

}

Функциональное программирование

Состояние - это значение со временем

Функциональное программирование является неотъемлемой частью объектно-ориентированного программирования. Функциональное программирование использует неизменяемое состояние.

Подробнее об этом здесь

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

Функциональное программирование может использовать больше памяти.

пример в FP


Optionals

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

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


API MM

Многие "утечки памяти" являются причиной Frameworksкоторые имеют функцию "очистки", которую вы, возможно, не вызывали. Хорошим примером является UIGraphicsEndImageContext() Контекст останется в памяти до тех пор, пока эта функция не будет вызвана. Он не очищается, когда функция, создавшая контекст, заканчивается или когда задействованное изображение установлено на нуль.

Другим хорошим примером является удаление ViewControllers. Это может иметь смысл переходить к одному VC, а затем отступать назад, но segue фактически создает VC. Сессия назад не уничтожает ВК. Вызовите dismissViewControllerAnimated(), чтобы удалить его из памяти.

Прочтите ссылки на классы и дважды проверьте, нет ли функций очистки.


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

Ответ 2

enter image description here

нажмите на название своего приложения в правом верхнем углу Xcode.

enter image description here

нажмите "Изменить схему" в появившемся меню.

enter image description here

убедитесь, что на левой стороне выбрано "RUN", затем щелкните вкладку диагностики в верхней части окна.

в заголовке "Управление памятью" проверьте флажок "enable Guard Malloc"

вы также можете попробовать проверить "распределенные объекты" и "стек malloc" под заголовком "logging"

больше информации о сторожевой карте, защитных краях и каракули можно найти здесь.



надеюсь, что это поможет!