Это мини-пост, напоминалка для самого себя о реализации такой важной и полезной в iOS разработке при дебаге функции, как подсчёт оперативной памяти, которую в данный момент занимает ваше приложение. Она очень хорошо помогает, когда нужно точно сказать, после вызова какой функции происходит скачок потребления RAM, но использование инструментов (Instruments) по каким-то причинам затруднено. Например, для меня сейчас эта функция – единственное спасение, потому что встроенные инструменты профилирования просто крэшатся при попытке их запустить.
Но, ближе к делу. Вот та самая функция подсчёта оперативной памяти, написанная на Swift 2.3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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, нужно внести несколько изменений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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]
Полезная статья? Их будет больше, если вы поддержите меня!