Функция подсчёта занимаемой приложением оперативной памяти на Swift

Это мини-пост, напоминалка для самого себя о реализации такой важной и полезной в iOS разработке при дебаге функции, как подсчёт оперативной памяти, которую в данный момент занимает ваше приложение. Она очень хорошо помогает, когда нужно точно сказать, после вызова какой функции происходит скачок потребления RAM, но использование инструментов (Instruments) по каким-то причинам затруднено. Например, для меня сейчас эта функция – единственное спасение, потому что встроенные инструменты профилирования просто крэшатся при попытке их запустить.

Но, ближе к делу. Вот та самая функция подсчёта оперативной памяти, написанная на Swift 2.3:

func report_memory() {
    var info = task_basic_info()
    var count = mach_msg_type_number_t(sizeofValue(info))/4

    let kerr: kern_return_t = withUnsafeMutablePointer(&info) {

        task_info(mach_task_self_,
            task_flavor_t(TASK_BASIC_INFO),
            task_info_t($0),
            &count)

    }

    if kerr == KERN_SUCCESS {
        print("Memory in use (in bytes): \(info.resident_size)")
    }
    else {
        print("Error with task_info(): " +
            (String.fromCString(mach_error_string(kerr)) ?? "unknown error"))
    }
}

Чтобы это всё заработало с новым Swift 3.0, нужно внести несколько изменений:

func report_memory() {
    var info = mach_task_basic_info()
    var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4

    let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
        $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
            task_info(mach_task_self_,
                      task_flavor_t(MACH_TASK_BASIC_INFO),
                      $0,
                      &count)
        }
    }

    if kerr == KERN_SUCCESS {
        print("Memory in use (in bytes): \(info.resident_size)")
    }
    else {
        print("Error with task_info(): " +
            (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
    }
}

Для любителей истории или для тех, кто не может себе позволить роскошь использовать Swift, вот версия на старом-добром Objective-C (который в этом примере скорее С, чем Objective):

void report_memory(void) {
  struct task_basic_info info;
  mach_msg_type_number_t size = sizeof(info);
  kern_return_t kerr = task_info(mach_task_self(),
                             TASK_BASIC_INFO,
                             (task_info_t)&info,
                             &size);
  if( kerr == KERN_SUCCESS ) {
    NSLog(@"Memory in use (in bytes): %u", info.resident_size);
  } else {
    NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
  }
}

У себя в проекте я объявил эту функцию статической в AppDelegate и просто вызываю её “через точку”. Я не стал приводить её название к принятому в iOS lowerCamelCase , чтобы лишний раз подчеркнуть её “служебность” и изначально “сишную” природу.


По материалам stackoverflow [0] и [1]

Полезная статья? Их будет больше, если вы поддержите меня!

https://money.yandex.ru/embed/small.xml?account=410011399843532&quickpay=small&yamoney-payment-type=on&button-text=06&button-size=l&button-color=orange&targets=%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D1%8E+%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82+lexpenz.com&default-sum=50&successURL=