Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e8852258a | ||
|
|
b37cfb06a9 |
@@ -12,10 +12,12 @@
|
|||||||
1B3F1C8ABF0ADFAA290FF6F6 /* MMSMCParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 375AA781A2AA0A20B119C7B7 /* MMSMCParser.m */; };
|
1B3F1C8ABF0ADFAA290FF6F6 /* MMSMCParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 375AA781A2AA0A20B119C7B7 /* MMSMCParser.m */; };
|
||||||
3C0AC14F803C813287D8A663 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007F48A5A599AB4E8D216D16 /* IOKit.framework */; };
|
3C0AC14F803C813287D8A663 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007F48A5A599AB4E8D216D16 /* IOKit.framework */; };
|
||||||
4419FE7554489B23976E2970 /* MMCPULoadProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = D68FC8100D08DB6202F46339 /* MMCPULoadProvider.m */; };
|
4419FE7554489B23976E2970 /* MMCPULoadProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = D68FC8100D08DB6202F46339 /* MMCPULoadProvider.m */; };
|
||||||
|
6201FD599FED061F6C736E8B /* MMMemoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099DCF7EF03A58ADA40A94A1 /* MMMemoryTests.swift */; };
|
||||||
88387CDAE2AC1CC74EF89B57 /* MacMonitorApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADEA6BD38BA8D887B1DB64A9 /* MacMonitorApp.swift */; };
|
88387CDAE2AC1CC74EF89B57 /* MacMonitorApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADEA6BD38BA8D887B1DB64A9 /* MacMonitorApp.swift */; };
|
||||||
9BCE74C5454F81EF80492E75 /* MacMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */; };
|
9BCE74C5454F81EF80492E75 /* MacMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */; };
|
||||||
A7609CE56D49EC3419987468 /* SystemTelemetryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B4E94FB2886C60D5548A2A /* SystemTelemetryStore.swift */; };
|
A7609CE56D49EC3419987468 /* SystemTelemetryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B4E94FB2886C60D5548A2A /* SystemTelemetryStore.swift */; };
|
||||||
A9FCAEC0BF27A419DB148C4A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E142AE61F9B87757997870DD /* ContentView.swift */; };
|
A9FCAEC0BF27A419DB148C4A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E142AE61F9B87757997870DD /* ContentView.swift */; };
|
||||||
|
B9C2D6574E808B517BA34C83 /* MMMemoryTelemetryProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 991AEEAF262F3C6BE930BC77 /* MMMemoryTelemetryProvider.m */; };
|
||||||
CD91FC663B19DA1FEA3D49D7 /* MMAppleSMCClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 5555436CD3CB8A73F5D6504F /* MMAppleSMCClient.m */; };
|
CD91FC663B19DA1FEA3D49D7 /* MMAppleSMCClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 5555436CD3CB8A73F5D6504F /* MMAppleSMCClient.m */; };
|
||||||
EAFAF5A10502D4ACC64F4720 /* MMTelemetryCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = F9F9AD1268F906761032AF4D /* MMTelemetryCoordinator.m */; };
|
EAFAF5A10502D4ACC64F4720 /* MMTelemetryCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = F9F9AD1268F906761032AF4D /* MMTelemetryCoordinator.m */; };
|
||||||
EC9FA3E4A119277B89E73F8D /* MMSMCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940D608A1AF80F75584E744E /* MMSMCTests.swift */; };
|
EC9FA3E4A119277B89E73F8D /* MMSMCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940D608A1AF80F75584E744E /* MMSMCTests.swift */; };
|
||||||
@@ -33,6 +35,8 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
007F48A5A599AB4E8D216D16 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
007F48A5A599AB4E8D216D16 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
||||||
|
0130BD1E18972DF9E2955334 /* MMMemoryTelemetryProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMMemoryTelemetryProvider.h; sourceTree = "<group>"; };
|
||||||
|
099DCF7EF03A58ADA40A94A1 /* MMMemoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMMemoryTests.swift; sourceTree = "<group>"; };
|
||||||
1AD9EEE571CD904BBCD1C96B /* MMSMCParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMSMCParser.h; sourceTree = "<group>"; };
|
1AD9EEE571CD904BBCD1C96B /* MMSMCParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMSMCParser.h; sourceTree = "<group>"; };
|
||||||
2345555FF9780B02A90CC7A9 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
2345555FF9780B02A90CC7A9 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||||
2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacMonitorTests.swift; sourceTree = "<group>"; };
|
2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacMonitorTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -47,6 +51,7 @@
|
|||||||
726005CB5A6C86E7D80D3CA0 /* MMAppleSMCClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMAppleSMCClient.h; sourceTree = "<group>"; };
|
726005CB5A6C86E7D80D3CA0 /* MMAppleSMCClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMAppleSMCClient.h; sourceTree = "<group>"; };
|
||||||
8FBB436F3D9472194D8C6EDD /* MMSMCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMSMCDefines.h; sourceTree = "<group>"; };
|
8FBB436F3D9472194D8C6EDD /* MMSMCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMSMCDefines.h; sourceTree = "<group>"; };
|
||||||
940D608A1AF80F75584E744E /* MMSMCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMSMCTests.swift; sourceTree = "<group>"; };
|
940D608A1AF80F75584E744E /* MMSMCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMSMCTests.swift; sourceTree = "<group>"; };
|
||||||
|
991AEEAF262F3C6BE930BC77 /* MMMemoryTelemetryProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMMemoryTelemetryProvider.m; sourceTree = "<group>"; };
|
||||||
ADEA6BD38BA8D887B1DB64A9 /* MacMonitorApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacMonitorApp.swift; sourceTree = "<group>"; };
|
ADEA6BD38BA8D887B1DB64A9 /* MacMonitorApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacMonitorApp.swift; sourceTree = "<group>"; };
|
||||||
D68FC8100D08DB6202F46339 /* MMCPULoadProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMCPULoadProvider.m; sourceTree = "<group>"; };
|
D68FC8100D08DB6202F46339 /* MMCPULoadProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMCPULoadProvider.m; sourceTree = "<group>"; };
|
||||||
E142AE61F9B87757997870DD /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
E142AE61F9B87757997870DD /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
@@ -131,6 +136,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
78383CED205BCA772701AE48 /* CPU */,
|
78383CED205BCA772701AE48 /* CPU */,
|
||||||
|
EE2F5EFC9DC33CEDA79A131F /* Memory */,
|
||||||
);
|
);
|
||||||
path = Telemetry;
|
path = Telemetry;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -157,6 +163,7 @@
|
|||||||
children = (
|
children = (
|
||||||
2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */,
|
2EC3EDFCD5C50CB352FCED87 /* MacMonitorTests.swift */,
|
||||||
4CE92B1A8D7FDBB6499448E1 /* MMCPULoadTests.swift */,
|
4CE92B1A8D7FDBB6499448E1 /* MMCPULoadTests.swift */,
|
||||||
|
099DCF7EF03A58ADA40A94A1 /* MMMemoryTests.swift */,
|
||||||
940D608A1AF80F75584E744E /* MMSMCTests.swift */,
|
940D608A1AF80F75584E744E /* MMSMCTests.swift */,
|
||||||
);
|
);
|
||||||
path = Tests;
|
path = Tests;
|
||||||
@@ -183,6 +190,15 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
EE2F5EFC9DC33CEDA79A131F /* Memory */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0130BD1E18972DF9E2955334 /* MMMemoryTelemetryProvider.h */,
|
||||||
|
991AEEAF262F3C6BE930BC77 /* MMMemoryTelemetryProvider.m */,
|
||||||
|
);
|
||||||
|
path = Memory;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -259,6 +275,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
160334CC765E091A7CBE21AA /* MMCPULoadTests.swift in Sources */,
|
160334CC765E091A7CBE21AA /* MMCPULoadTests.swift in Sources */,
|
||||||
|
6201FD599FED061F6C736E8B /* MMMemoryTests.swift in Sources */,
|
||||||
EC9FA3E4A119277B89E73F8D /* MMSMCTests.swift in Sources */,
|
EC9FA3E4A119277B89E73F8D /* MMSMCTests.swift in Sources */,
|
||||||
9BCE74C5454F81EF80492E75 /* MacMonitorTests.swift in Sources */,
|
9BCE74C5454F81EF80492E75 /* MacMonitorTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
@@ -271,6 +288,7 @@
|
|||||||
A9FCAEC0BF27A419DB148C4A /* ContentView.swift in Sources */,
|
A9FCAEC0BF27A419DB148C4A /* ContentView.swift in Sources */,
|
||||||
CD91FC663B19DA1FEA3D49D7 /* MMAppleSMCClient.m in Sources */,
|
CD91FC663B19DA1FEA3D49D7 /* MMAppleSMCClient.m in Sources */,
|
||||||
4419FE7554489B23976E2970 /* MMCPULoadProvider.m in Sources */,
|
4419FE7554489B23976E2970 /* MMCPULoadProvider.m in Sources */,
|
||||||
|
B9C2D6574E808B517BA34C83 /* MMMemoryTelemetryProvider.m in Sources */,
|
||||||
1B3F1C8ABF0ADFAA290FF6F6 /* MMSMCParser.m in Sources */,
|
1B3F1C8ABF0ADFAA290FF6F6 /* MMSMCParser.m in Sources */,
|
||||||
EAFAF5A10502D4ACC64F4720 /* MMTelemetryCoordinator.m in Sources */,
|
EAFAF5A10502D4ACC64F4720 /* MMTelemetryCoordinator.m in Sources */,
|
||||||
88387CDAE2AC1CC74EF89B57 /* MacMonitorApp.swift in Sources */,
|
88387CDAE2AC1CC74EF89B57 /* MacMonitorApp.swift in Sources */,
|
||||||
|
|||||||
@@ -13,5 +13,6 @@
|
|||||||
|
|
||||||
// Telemetry Providers
|
// Telemetry Providers
|
||||||
#import "MMCPULoadProvider.h"
|
#import "MMCPULoadProvider.h"
|
||||||
|
#import "MMMemoryTelemetryProvider.h"
|
||||||
|
|
||||||
#endif /* MacMonitor_Bridging_Header_h */
|
#endif /* MacMonitor_Bridging_Header_h */
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef MMMemoryTelemetryProvider_h
|
||||||
|
#define MMMemoryTelemetryProvider_h
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <mach/mach.h>
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
#import "MMTelemetryProvider.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MMMemoryTelemetryProvider
|
||||||
|
* Samples Mach virtual memory statistics, wired/active/inactive/compressed memory allocations,
|
||||||
|
* swap usage, and system-wide memory pressure levels.
|
||||||
|
*/
|
||||||
|
@interface MMMemoryTelemetryProvider : NSObject <MMTelemetryProvider>
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) uint64_t totalPhysicalMemoryBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deterministic helper method for unit testing VM metric calculations.
|
||||||
|
*/
|
||||||
|
+ (NSDictionary<NSString *, id> *)calculateMemoryMetricsWithVMInfo:(const vm_statistics64_data_t *)vmInfo
|
||||||
|
pageSize:(vm_size_t)pageSize
|
||||||
|
totalPhysicalRAM:(uint64_t)totalRAM
|
||||||
|
swapUsage:(const struct xsw_usage * _Nullable)swap;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif /* MMMemoryTelemetryProvider_h */
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
#import "MMMemoryTelemetryProvider.h"
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
|
||||||
|
@interface MMMemoryTelemetryProvider () {
|
||||||
|
uint64_t _totalPhysicalMemoryBytes;
|
||||||
|
vm_size_t _pageSize;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MMMemoryTelemetryProvider
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
// Read physical memory size
|
||||||
|
uint64_t memSize = 0;
|
||||||
|
size_t size = sizeof(memSize);
|
||||||
|
sysctlbyname("hw.memsize", &memSize, &size, NULL, 0);
|
||||||
|
_totalPhysicalMemoryBytes = memSize;
|
||||||
|
|
||||||
|
// Read virtual memory page size
|
||||||
|
vm_size_t pSize = 4096;
|
||||||
|
host_page_size(mach_host_self(), &pSize);
|
||||||
|
_pageSize = pSize;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MMTelemetryDomain)domain {
|
||||||
|
return MMTelemetryDomainMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)providerIdentifier {
|
||||||
|
return @"com.i3omb.macmonitor.telemetry.memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isAvailable {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint64_t)totalPhysicalMemoryBytes {
|
||||||
|
return _totalPhysicalMemoryBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)calculateMemoryMetricsWithVMInfo:(const vm_statistics64_data_t *)vmInfo
|
||||||
|
pageSize:(vm_size_t)pageSize
|
||||||
|
totalPhysicalRAM:(uint64_t)totalRAM
|
||||||
|
swapUsage:(const struct xsw_usage * _Nullable)swap {
|
||||||
|
if (!vmInfo) return @{};
|
||||||
|
|
||||||
|
uint64_t appMemory = (vmInfo->internal_page_count > vmInfo->purgeable_count)
|
||||||
|
? (uint64_t)(vmInfo->internal_page_count - vmInfo->purgeable_count) * pageSize
|
||||||
|
: 0;
|
||||||
|
uint64_t wired = (uint64_t)vmInfo->wire_count * pageSize;
|
||||||
|
uint64_t compressed = (uint64_t)vmInfo->compressor_page_count * pageSize;
|
||||||
|
uint64_t used = appMemory + wired + compressed;
|
||||||
|
|
||||||
|
uint64_t freeRAM = (uint64_t)vmInfo->free_count * pageSize;
|
||||||
|
uint64_t purgeable = (uint64_t)vmInfo->purgeable_count * pageSize;
|
||||||
|
uint64_t active = (uint64_t)vmInfo->active_count * pageSize;
|
||||||
|
uint64_t inactive = (uint64_t)vmInfo->inactive_count * pageSize;
|
||||||
|
|
||||||
|
// Calculate Memory Pressure percentage
|
||||||
|
uint64_t availableForUse = (uint64_t)(vmInfo->free_count + vmInfo->inactive_count) * pageSize;
|
||||||
|
double pressurePct = 0.0;
|
||||||
|
if (totalRAM > 0) {
|
||||||
|
pressurePct = (1.0 - ((double)availableForUse / (double)totalRAM)) * 100.0;
|
||||||
|
if (pressurePct < 0.0) pressurePct = 0.0;
|
||||||
|
if (pressurePct > 100.0) pressurePct = 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *pressureStatus = @"Normal";
|
||||||
|
if (pressurePct >= 80.0) {
|
||||||
|
pressureStatus = @"Critical";
|
||||||
|
} else if (pressurePct >= 60.0) {
|
||||||
|
pressureStatus = @"Warning";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t swapTotal = swap ? swap->xsu_total : 0;
|
||||||
|
uint64_t swapUsed = swap ? swap->xsu_used : 0;
|
||||||
|
uint64_t swapFree = swap ? swap->xsu_avail : 0;
|
||||||
|
|
||||||
|
return @{
|
||||||
|
@"totalBytes": @(totalRAM),
|
||||||
|
@"usedBytes": @(used),
|
||||||
|
@"freeBytes": @(freeRAM),
|
||||||
|
@"appMemoryBytes": @(appMemory),
|
||||||
|
@"wiredBytes": @(wired),
|
||||||
|
@"compressedBytes": @(compressed),
|
||||||
|
@"purgeableBytes": @(purgeable),
|
||||||
|
@"activeBytes": @(active),
|
||||||
|
@"inactiveBytes": @(inactive),
|
||||||
|
@"memoryPressurePercent": @(pressurePct),
|
||||||
|
@"memoryPressureStatus": pressureStatus,
|
||||||
|
@"swapTotalBytes": @(swapTotal),
|
||||||
|
@"swapUsedBytes": @(swapUsed),
|
||||||
|
@"swapFreeBytes": @(swapFree)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable NSDictionary<NSString *, id> *)sampleTelemetryWithError:(NSError **)error {
|
||||||
|
vm_statistics64_data_t vmInfo = {0};
|
||||||
|
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
|
||||||
|
|
||||||
|
kern_return_t kr = host_statistics64(
|
||||||
|
mach_host_self(),
|
||||||
|
HOST_VM_INFO64,
|
||||||
|
(host_info64_t)&vmInfo,
|
||||||
|
&count
|
||||||
|
);
|
||||||
|
|
||||||
|
if (kr != KERN_SUCCESS) {
|
||||||
|
if (error) {
|
||||||
|
*error = [NSError errorWithDomain:@"com.i3omb.MacMonitor.Memory"
|
||||||
|
code:kr
|
||||||
|
userInfo:@{NSLocalizedDescriptionKey: @"host_statistics64 failed to sample VM metrics"}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read swap usage
|
||||||
|
struct xsw_usage swap = {0};
|
||||||
|
size_t swapSize = sizeof(swap);
|
||||||
|
struct xsw_usage *swapPtr = NULL;
|
||||||
|
if (sysctlbyname("vm.swapusage", &swap, &swapSize, NULL, 0) == 0) {
|
||||||
|
swapPtr = &swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [MMMemoryTelemetryProvider calculateMemoryMetricsWithVMInfo:&vmInfo
|
||||||
|
pageSize:_pageSize
|
||||||
|
totalPhysicalRAM:_totalPhysicalMemoryBytes
|
||||||
|
swapUsage:swapPtr];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import XCTest
|
||||||
|
@testable import MacMonitor
|
||||||
|
|
||||||
|
final class MMMemoryTests: XCTestCase {
|
||||||
|
|
||||||
|
func testMemoryMetricCalculation() {
|
||||||
|
var vmInfo = vm_statistics64_data_t()
|
||||||
|
let pageSize: vm_size_t = 4096
|
||||||
|
let totalRAM: UInt64 = 16 * 1024 * 1024 * 1024 // 16 GB
|
||||||
|
|
||||||
|
// 1GB wired (262144 pages), 2GB app (524288 pages), 1GB compressed (262144 pages)
|
||||||
|
vmInfo.wire_count = 262_144
|
||||||
|
vmInfo.internal_page_count = 524_288
|
||||||
|
vmInfo.purgeable_count = 0
|
||||||
|
vmInfo.compressor_page_count = 262_144
|
||||||
|
vmInfo.active_count = 524_288
|
||||||
|
vmInfo.inactive_count = 1_048_576 // 4GB
|
||||||
|
vmInfo.free_count = 2_097_152 // 8GB
|
||||||
|
|
||||||
|
var swap = xsw_usage()
|
||||||
|
swap.xsu_total = 2 * 1024 * 1024 * 1024
|
||||||
|
swap.xsu_used = 512 * 1024 * 1024
|
||||||
|
swap.xsu_avail = swap.xsu_total - swap.xsu_used
|
||||||
|
|
||||||
|
withUnsafePointer(to: vmInfo) { vmPtr in
|
||||||
|
withUnsafePointer(to: swap) { swapPtr in
|
||||||
|
let metrics = MMMemoryTelemetryProvider.calculateMemoryMetrics(
|
||||||
|
withVMInfo: vmPtr,
|
||||||
|
pageSize: pageSize,
|
||||||
|
totalPhysicalRAM: totalRAM,
|
||||||
|
swapUsage: swapPtr
|
||||||
|
)
|
||||||
|
|
||||||
|
let wired = metrics["wiredBytes"] as? UInt64 ?? 0
|
||||||
|
let app = metrics["appMemoryBytes"] as? UInt64 ?? 0
|
||||||
|
let compressed = metrics["compressedBytes"] as? UInt64 ?? 0
|
||||||
|
let used = metrics["usedBytes"] as? UInt64 ?? 0
|
||||||
|
let pressureStatus = metrics["memoryPressureStatus"] as? String ?? ""
|
||||||
|
|
||||||
|
XCTAssertEqual(wired, 1024 * 1024 * 1024)
|
||||||
|
XCTAssertEqual(app, 2 * 1024 * 1024 * 1024)
|
||||||
|
XCTAssertEqual(compressed, 1024 * 1024 * 1024)
|
||||||
|
XCTAssertEqual(used, 4 * 1024 * 1024 * 1024)
|
||||||
|
XCTAssertEqual(pressureStatus, "Normal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLiveMemoryProvider() throws {
|
||||||
|
let provider = MMMemoryTelemetryProvider()
|
||||||
|
XCTAssertTrue(provider.isAvailable)
|
||||||
|
XCTAssertEqual(provider.domain, .memory)
|
||||||
|
XCTAssertGreaterThan(provider.totalPhysicalMemoryBytes, 0)
|
||||||
|
|
||||||
|
let sample = try provider.sampleTelemetry()
|
||||||
|
let total = sample["totalBytes"] as? UInt64 ?? 0
|
||||||
|
let used = sample["usedBytes"] as? UInt64 ?? 0
|
||||||
|
let free = sample["freeBytes"] as? UInt64 ?? 0
|
||||||
|
|
||||||
|
XCTAssertGreaterThan(total, 0)
|
||||||
|
XCTAssertGreaterThan(used, 0)
|
||||||
|
XCTAssertGreaterThanOrEqual(free, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user