iPhone에서 프로그래밍 방식으로 메모리 사용량 검색
언제든지 프로그래밍 방식으로 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가 연결되는 코드는 장치에서 사용할 수 있는 메모리 양과 메모리 유형을 제공합니다.
이는 2019년 7월 1일 모하비 10.4.6의 Xcode 11에서 테스트되었으며, 2020년 11월 5일 현재 Xcode 11.3에서 테스트되었습니다.
이전의 모든 답변은 잘못된 결과를 반환합니다.
두명Swift
버전은 아래와 같습니다.
애플 퀸이 작성한 기대가치를 얻는 방법은 다음과 같습니다. "The Eskimo!"
이는 다음의 변수를 사용합니다.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)을 쉽게 반환하여 표시할 수 있습니다.이를 자동화된 UIT 테스트 제품군의 일부로 사용하여 동일한 테스트를 여러 번 반복하기 전과 후에 사용된 메모리를 기록하여 잠재적인 누출이나 할당을 조사해야 하는지 확인합니다.
// 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
유효한 소수점 이하 두 자리만 반환합니다.
머리글: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));
}
}
NSLog()에 리크 상태를 신속하게 표시하도록 report_memory()가 향상되었습니다.
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;
}
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))")
}
}
스위프트 3.1 (2017년 8월 8일 기준)
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"))
}
}
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);
}
언급URL : https://stackoverflow.com/questions/787160/programmatically-retrieve-memory-usage-on-iphone
'programing' 카테고리의 다른 글
yup의 물건을 사용하는 방법.타자기로 모양을 만들 수 있습니까? (0) | 2023.06.11 |
---|---|
VBA에서 양식이 닫힐 때 코드 실행(Excel 2007) (0) | 2023.06.11 |
Android에서 글꼴을 변경하는 방법 TextView 제품군 (0) | 2023.06.01 |
루비의 문자열 연결 (0) | 2023.06.01 |
레일 모델, 뷰, 컨트롤러 및 도우미: 무엇이 가능합니까? (0) | 2023.06.01 |