16

How to get memory usage of my application and system in swift by programatically?

not only system, but also my application

9

3 Answers 3

23

For Swift 3.0 you can use the following function.

func report_memory() {
    var taskInfo = 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: &taskInfo) {
        $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 used in bytes: \(taskInfo.resident_size)")
    }
    else {
        print("Error with task_info(): " +
            (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

thx, by the way,where can i find the documentation of the apple's Darwin api, such as mach_task_basic_info kern_return_t
well there is this, opensource.apple.com/source/xnu/xnu-2050.9.2/osfmk/mach/… , but i am not sure if there is anything else Apple specific documentation.
The code works, but the value get by the code is different with other App(BMSSM/sys Status/etc). Dont know which one is correct.
The memory usage using this code shows x3 times the memory usage from the debugger. Why?
this answer gives a wrong result. check the one below by mAc, it works correctly
|
18

Found and tested this on XCode 12.2 and Mac OS Catalina 10.15.6 and it works like charm:

func memoryFootprint() -> Float? {
    // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too
    // complex for the Swift C importer, so we have to define them ourselves.
    let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)
    let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout<integer_t>.size)
    var info = task_vm_info_data_t()
    var count = TASK_VM_INFO_COUNT
    let kr = withUnsafeMutablePointer(to: &info) { infoPtr in
        infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in
            task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)
        }
    }
    guard
        kr == KERN_SUCCESS,
        count >= TASK_VM_INFO_REV1_COUNT
    else { return nil }
    
    let usedBytes = Float(info.phys_footprint)
    return usedBytes
    
}

func formattedMemoryFootprint() -> String {
    let usedBytes: UInt64? = UInt64(self.memoryFootprint() ?? 0)
    let usedMB = Double(usedBytes ?? 0) / 1024 / 1024
    let usedMBAsString: String = "Memory Used by App: \(usedMB)MB"
    return usedMBAsString
}

Hope this helps someone too :)

4 Comments

This is not portable. Only works on Macs
Are you using a windows machine or other to develop an iOS app?
1. I do not do iOS. 2: my applications run in docker
For those who are wondering: This code returns the memory usage of the app that runs it. It is not returning the overall systems memory usage. How would we do that?
7

mAc's answers but without force unwrapping:

func memoryFootprint() -> String {
    // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too
    // complex for the Swift C importer, so we have to define them ourselves.
    let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)
    guard let offset = MemoryLayout.offset(of: \task_vm_info_data_t.min_address) else {return "memory: NA"}
    let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(offset / MemoryLayout<integer_t>.size)
    var info = task_vm_info_data_t()
    var count = TASK_VM_INFO_COUNT
    let kr = withUnsafeMutablePointer(to: &info) { infoPtr in
        infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in
            task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)
        }
    }
    guard
        kr == KERN_SUCCESS,
        count >= TASK_VM_INFO_REV1_COUNT
    else { return "memory: NA" }
    
    let usedBytes = Float(info.phys_footprint)
    let usedBytesInt: UInt64 = UInt64(usedBytes)
    let usedMB = usedBytesInt / 1024 / 1024
    let usedMBAsString: String = "memory: \(usedMB) MB"
    return usedMBAsString
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.