ฉันกำลังพยายามดึงข้อมูลจำนวนหน่วยความจำที่แอพ iPhone ของฉันใช้อยู่ตลอดเวลาโดยใช้โปรแกรม ใช่ฉันทราบเกี่ยวกับ ObjectAlloc / Leaks ฉันไม่สนใจสิ่งเหล่านี้เพียง แต่รู้ว่าเป็นไปได้ไหมที่จะเขียนโค้ดและรับจำนวนไบต์ที่ใช้และรายงานผ่าน NSLog
ขอบคุณ.
ฉันกำลังพยายามดึงข้อมูลจำนวนหน่วยความจำที่แอพ iPhone ของฉันใช้อยู่ตลอดเวลาโดยใช้โปรแกรม ใช่ฉันทราบเกี่ยวกับ ObjectAlloc / Leaks ฉันไม่สนใจสิ่งเหล่านี้เพียง แต่รู้ว่าเป็นไปได้ไหมที่จะเขียนโค้ดและรับจำนวนไบต์ที่ใช้และรายงานผ่าน NSLog
ขอบคุณ.
คำตอบ:
หากต้องการรับไบต์จริงของหน่วยความจำที่แอปพลิเคชันของคุณใช้คุณสามารถทำสิ่งต่างๆดังตัวอย่างด้านล่าง อย่างไรก็ตามคุณควรทำความคุ้นเคยกับเครื่องมือทำโปรไฟล์ต่างๆอย่างแท้จริงรวมทั้งได้รับการออกแบบมาเพื่อให้คุณได้ภาพรวมการใช้งานที่ดีขึ้นมาก
#import <mach/mach.h>
// ...
void report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = TASK_BASIC_INFO_COUNT;
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): %lu", info.resident_size);
NSLog(@"Memory in use (in MiB): %f", ((CGFloat)info.resident_size / 1048576));
} else {
NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
}
นอกจากนี้ยังมีฟิลด์ในโครงสร้าง info.virtual_size ซึ่งจะให้จำนวนไบต์หน่วยความจำเสมือนที่มีอยู่ (หรือหน่วยความจำที่จัดสรรให้กับแอปพลิเคชันของคุณเป็นหน่วยความจำเสมือนที่มีศักยภาพในทุกเหตุการณ์) รหัสที่ pgb เชื่อมโยงไปจะให้จำนวนหน่วยความจำที่มีอยู่ในอุปกรณ์และหน่วยความจำประเภทใด
ส่วนหัวสำหรับTASK_BASIC_INFO
พูดว่า:
/* Don't use this, use MACH_TASK_BASIC_INFO instead */
นี่คือเวอร์ชันที่ใช้MACH_TASK_BASIC_INFO
:
void report_memory(void)
{
struct mach_task_basic_info info;
mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(),
MACH_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));
}
}
ต่อไปนี้คือ report_memory () ที่ปรับปรุงเพื่อแสดงสถานะการรั่วไหลอย่างรวดเร็วใน NSLog ()
void report_memory(void) {
static unsigned last_resident_size=0;
static unsigned greatest = 0;
static unsigned last_greatest = 0;
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 ) {
int diff = (int)info.resident_size - (int)last_resident_size;
unsigned latest = info.resident_size;
if( latest > greatest ) greatest = latest; // track greatest mem usage
int greatest_diff = greatest - last_greatest;
int latest_greatest_diff = latest - greatest;
NSLog(@"Mem: %10u (%10d) : %10d : greatest: %10u (%d)", info.resident_size, diff,
latest_greatest_diff,
greatest, greatest_diff );
} else {
NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
last_resident_size = info.resident_size;
last_greatest = greatest;
}
สิ่งนี้ได้รับการทดสอบบน Xcode 11 ใน Mojave 10.4.6 เมื่อ 07/01/2019
ทุกคำตอบก่อนหน้านี้กลับผลลัพธ์ไม่ถูกต้อง
นี่คือวิธีรับค่าที่คาดหวังซึ่งเขียนโดย Quinn“ The Eskimo!” ของ Apple
นี้ใช้phys_footprint
var จากDarwin > Mach > task_info
และใกล้เคียงกับค่าในวัดหน่วยความจำใน Xcode ของ Debug นำทาง
ค่าที่ส่งคืนเป็นไบต์
https://forums.developer.apple.com/thread/105088#357415
รหัสเดิมมีดังนี้
func memoryFootprint() -> mach_vm_size_t? {
// 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 }
return info.phys_footprint
}
การแก้ไขเล็กน้อยเพื่อสร้างชุดระดับคลาสของวิธีการ Swift ช่วยให้สามารถคืนค่าไบต์จริงและเอาต์พุตที่จัดรูปแบบเป็น MB สำหรับการแสดงผลได้อย่างง่ายดาย ฉันใช้สิ่งนี้เป็นส่วนหนึ่งของชุด UITest อัตโนมัติเพื่อบันทึกหน่วยความจำที่ใช้ก่อนและหลังการทดสอบเดียวกันซ้ำหลายครั้งเพื่อดูว่าเรามีการรั่วไหลหรือการจัดสรรที่เราต้องตรวจสอบหรือไม่
// Created by Alex Zavatone on 8/1/19.
//
class Memory: NSObject {
// From Quinn the Eskimo at Apple.
// https://forums.developer.apple.com/thread/105088#357415
class 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
}
class func formattedMemoryFootprint() -> String
{
let usedBytes: UInt64? = UInt64(self.memoryFootprint() ?? 0)
let usedMB = Double(usedBytes ?? 0) / 1024 / 1024
let usedMBAsString: String = "\(usedMB)MB"
return usedMBAsString
}
}
สนุก!
หมายเหตุ: ผู้เขียนโค้ดกล้าได้กล้าเสียอาจต้องการเพิ่มตัวจัดรูปแบบคงที่ให้กับคลาสเพื่อให้usedMBAsString
ส่งกลับทศนิยมที่มีนัยสำคัญเพียง 2 ตำแหน่งเท่านั้น
คำตอบของJason Coco อย่างรวดเร็ว:
func reportMemory() {
let name = mach_task_self_
let flavor = task_flavor_t(TASK_BASIC_INFO)
let basicInfo = task_basic_info()
var size: mach_msg_type_number_t = mach_msg_type_number_t(sizeofValue(basicInfo))
let pointerOfBasicInfo = UnsafeMutablePointer<task_basic_info>.alloc(1)
let kerr: kern_return_t = task_info(name, flavor, UnsafeMutablePointer(pointerOfBasicInfo), &size)
let info = pointerOfBasicInfo.move()
pointerOfBasicInfo.dealloc(1)
if kerr == KERN_SUCCESS {
print("Memory in use (in bytes): \(info.resident_size)")
} else {
print("error with task info(): \(mach_error_string(kerr))")
}
}
Swift 3.1 (ณ วันที่ 8 สิงหาคม 2017)
func getMemory() {
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 {
let usedMegabytes = taskInfo.resident_size/(1024*1024)
print("used megabytes: \(usedMegabytes)")
} else {
print("Error with task_info(): " +
(String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
}
}
(1024*1024)
ไม่ใช่ด้วย1000000
เพื่อให้ได้เมกะไบต์จากไบต์
นี่คือเวอร์ชัน Swift 3:
func mach_task_self() -> task_t {
return mach_task_self_
}
func getMegabytesUsed() -> Float? {
var info = mach_task_basic_info()
var count = mach_msg_type_number_t(MemoryLayout.size(ofValue: info) / MemoryLayout<integer_t>.size)
let kerr = withUnsafeMutablePointer(to: &info) { infoPtr in
return infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { (machPtr: UnsafeMutablePointer<integer_t>) in
return task_info(
mach_task_self(),
task_flavor_t(MACH_TASK_BASIC_INFO),
machPtr,
&count
)
}
}
guard kerr == KERN_SUCCESS else {
return nil
}
return Float(info.resident_size) / (1024 * 1024)
}
size_t memoryFootprint()
{
task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if (result != KERN_SUCCESS)
return 0;
return static_cast<size_t>(vmInfo.phys_footprint);
}
ด้านล่างนี้คือคำตอบที่ถูกต้อง:
``
float GetTotalPhysicsMemory()
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kr;
kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
if (kr == KERN_SUCCESS)
return (float)(info.resident_size) / 1024.0 / 1024.0;
else
return 0;
}
``