Это мини-пост, напоминалка для самого себя о реализации такой важной и полезной в 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]
Полезная статья? Их будет больше, если вы поддержите меня!