mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
BugFix: Memory usage
This commit is contained in:
parent
7a1945dd21
commit
267c4ba092
3 changed files with 79 additions and 61 deletions
|
|
@ -36,35 +36,20 @@ struct ContentView: View {
|
||||||
|
|
||||||
// Dynamic sizing based on view type and graph count with smooth transitions
|
// Dynamic sizing based on view type and graph count with smooth transitions
|
||||||
var dynamicNotchSize: CGSize {
|
var dynamicNotchSize: CGSize {
|
||||||
// Use minimalistic or normal size based on settings
|
|
||||||
let baseSize = Defaults[.enableMinimalisticUI] ? minimalisticOpenNotchSize : openNotchSize
|
let baseSize = Defaults[.enableMinimalisticUI] ? minimalisticOpenNotchSize : openNotchSize
|
||||||
|
|
||||||
// Always return the target size for the current view to ensure smooth transitions
|
guard coordinator.currentView == .stats else {
|
||||||
let targetSize: CGSize
|
return baseSize
|
||||||
|
|
||||||
if coordinator.currentView == .stats {
|
|
||||||
// Count enabled graphs using the same logic as NotchStatsView
|
|
||||||
var enabledGraphsCount = 0
|
|
||||||
if showCpuGraph { enabledGraphsCount += 1 }
|
|
||||||
if showMemoryGraph { enabledGraphsCount += 1 }
|
|
||||||
if showGpuGraph { enabledGraphsCount += 1 }
|
|
||||||
if showNetworkGraph { enabledGraphsCount += 1 }
|
|
||||||
if showDiskGraph { enabledGraphsCount += 1 }
|
|
||||||
|
|
||||||
if enabledGraphsCount > 3 {
|
|
||||||
// Expand height for 4+ graphs
|
|
||||||
targetSize = CGSize(
|
|
||||||
width: baseSize.width,
|
|
||||||
height: baseSize.height + 65 // Add extra height for second row
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
targetSize = baseSize
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
targetSize = baseSize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return targetSize
|
let rows = statsRowCount()
|
||||||
|
if rows <= 1 {
|
||||||
|
return baseSize
|
||||||
|
}
|
||||||
|
|
||||||
|
let additionalRows = max(rows - 1, 0)
|
||||||
|
let extraHeight = CGFloat(additionalRows) * statsAdditionalRowHeight
|
||||||
|
return CGSize(width: baseSize.width, height: baseSize.height + extraHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -96,6 +81,7 @@ struct ContentView: View {
|
||||||
|
|
||||||
private let extendedHoverPadding: CGFloat = 30
|
private let extendedHoverPadding: CGFloat = 30
|
||||||
private let zeroHeightHoverPadding: CGFloat = 10
|
private let zeroHeightHoverPadding: CGFloat = 10
|
||||||
|
private let statsAdditionalRowHeight: CGFloat = 110
|
||||||
|
|
||||||
// Use minimalistic corner radius ONLY when opened, keep normal when closed
|
// Use minimalistic corner radius ONLY when opened, keep normal when closed
|
||||||
private var activeCornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) {
|
private var activeCornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) {
|
||||||
|
|
@ -266,10 +252,12 @@ struct ContentView: View {
|
||||||
isViewTransitioning = false
|
isViewTransitioning = false
|
||||||
|
|
||||||
// Check if this transition will cause a size change
|
// Check if this transition will cause a size change
|
||||||
let oldSize = oldValue == .stats && statsTabHasExpandedHeight() ?
|
let baseOpenSize = Defaults[.enableMinimalisticUI] ? minimalisticOpenNotchSize : openNotchSize
|
||||||
CGSize(width: openNotchSize.width, height: openNotchSize.height + 65) : openNotchSize
|
let expandedHeight = baseOpenSize.height + statsAdditionalRowHeight
|
||||||
let newSize = newValue == .stats && statsTabHasExpandedHeight() ?
|
let oldSize = oldValue == .stats && statsTabHasExpandedHeight() ?
|
||||||
CGSize(width: openNotchSize.width, height: openNotchSize.height + 65) : openNotchSize
|
CGSize(width: baseOpenSize.width, height: expandedHeight) : baseOpenSize
|
||||||
|
let newSize = newValue == .stats && statsTabHasExpandedHeight() ?
|
||||||
|
CGSize(width: baseOpenSize.width, height: expandedHeight) : baseOpenSize
|
||||||
let sizeWillChange = oldSize != newSize
|
let sizeWillChange = oldSize != newSize
|
||||||
|
|
||||||
// Set flags for transition tracking
|
// Set flags for transition tracking
|
||||||
|
|
@ -780,13 +768,23 @@ struct ContentView: View {
|
||||||
|
|
||||||
// Helper to check if stats tab has 4+ graphs (needs expanded height)
|
// Helper to check if stats tab has 4+ graphs (needs expanded height)
|
||||||
private func statsTabHasExpandedHeight() -> Bool {
|
private func statsTabHasExpandedHeight() -> Bool {
|
||||||
|
return statsRowCount() > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
private func enabledStatsGraphCount() -> Int {
|
||||||
var enabledCount = 0
|
var enabledCount = 0
|
||||||
if showCpuGraph { enabledCount += 1 }
|
if showCpuGraph { enabledCount += 1 }
|
||||||
if showMemoryGraph { enabledCount += 1 }
|
if showMemoryGraph { enabledCount += 1 }
|
||||||
if showGpuGraph { enabledCount += 1 }
|
if showGpuGraph { enabledCount += 1 }
|
||||||
if showNetworkGraph { enabledCount += 1 }
|
if showNetworkGraph { enabledCount += 1 }
|
||||||
if showDiskGraph { enabledCount += 1 }
|
if showDiskGraph { enabledCount += 1 }
|
||||||
return enabledCount > 3
|
return enabledCount
|
||||||
|
}
|
||||||
|
|
||||||
|
private func statsRowCount() -> Int {
|
||||||
|
let count = enabledStatsGraphCount()
|
||||||
|
if count == 0 { return 0 }
|
||||||
|
return count <= 3 ? 1 : 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Gesture Handling
|
// MARK: - Gesture Handling
|
||||||
|
|
|
||||||
|
|
@ -227,10 +227,15 @@ struct DetailRow: View {
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: 12, weight: .medium))
|
.font(.system(size: 12, weight: .medium))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
.lineLimit(1)
|
||||||
|
.layoutPriority(0.5)
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(value)
|
Text(value)
|
||||||
.font(.system(size: 13, weight: .semibold, design: .monospaced))
|
.font(.system(size: 13, weight: .semibold, design: .monospaced))
|
||||||
.foregroundColor(.primary)
|
.foregroundColor(.primary)
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.85)
|
||||||
|
.layoutPriority(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -400,6 +400,19 @@ class StatsManager: ObservableObject {
|
||||||
private var delayedStopTimer: Timer?
|
private var delayedStopTimer: Timer?
|
||||||
private var delayedStartTimer: Timer?
|
private var delayedStartTimer: Timer?
|
||||||
private let maxHistoryPoints = 30
|
private let maxHistoryPoints = 30
|
||||||
|
private let totalPhysicalMemory: UInt64 = {
|
||||||
|
var stats = host_basic_info()
|
||||||
|
var count = mach_msg_type_number_t(MemoryLayout<host_basic_info_data_t>.size / MemoryLayout<integer_t>.size)
|
||||||
|
let result = withUnsafeMutablePointer(to: &stats) {
|
||||||
|
$0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) {
|
||||||
|
host_info(mach_host_self(), HOST_BASIC_INFO, $0, &count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if result == KERN_SUCCESS {
|
||||||
|
return UInt64(stats.max_mem)
|
||||||
|
}
|
||||||
|
return UInt64(ProcessInfo.processInfo.physicalMemory)
|
||||||
|
}()
|
||||||
|
|
||||||
// Smart monitoring state
|
// Smart monitoring state
|
||||||
private var shouldMonitorForStats: Bool = false
|
private var shouldMonitorForStats: Bool = false
|
||||||
|
|
@ -759,30 +772,32 @@ class StatsManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
let pageSize = UInt64(vm_kernel_page_size)
|
let pageSize = UInt64(vm_kernel_page_size)
|
||||||
let freeCount = UInt64(vmStatistics.free_count) + UInt64(vmStatistics.speculative_count)
|
let freeBytes = UInt64(vmStatistics.free_count) * pageSize
|
||||||
let activeCount = UInt64(vmStatistics.active_count)
|
let speculativeBytes = UInt64(vmStatistics.speculative_count) * pageSize
|
||||||
let inactiveCount = UInt64(vmStatistics.inactive_count)
|
let activeBytes = UInt64(vmStatistics.active_count) * pageSize
|
||||||
let wiredCount = UInt64(vmStatistics.wire_count)
|
let inactiveBytes = UInt64(vmStatistics.inactive_count) * pageSize
|
||||||
let compressorCount = UInt64(vmStatistics.compressor_page_count)
|
let wiredBytes = UInt64(vmStatistics.wire_count) * pageSize
|
||||||
|
let compressedBytes = UInt64(vmStatistics.compressor_page_count) * pageSize
|
||||||
|
let purgeableBytes = UInt64(vmStatistics.purgeable_count) * pageSize
|
||||||
|
let externalBytes = UInt64(vmStatistics.external_page_count) * pageSize
|
||||||
|
|
||||||
let totalMemory = (freeCount + activeCount + inactiveCount + wiredCount) * pageSize
|
let totalMemoryBytes: UInt64
|
||||||
guard totalMemory > 0 else {
|
if totalPhysicalMemory > 0 {
|
||||||
|
totalMemoryBytes = totalPhysicalMemory
|
||||||
|
} else {
|
||||||
|
totalMemoryBytes = freeBytes + speculativeBytes + activeBytes + inactiveBytes + wiredBytes + compressedBytes
|
||||||
|
}
|
||||||
|
guard totalMemoryBytes > 0 else {
|
||||||
return (0.0, .zero)
|
return (0.0, .zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
let freeMemory = freeCount * pageSize
|
let usedWithoutCache = activeBytes + inactiveBytes + speculativeBytes + wiredBytes + compressedBytes
|
||||||
let speculativeCount = UInt64(vmStatistics.speculative_count)
|
let cacheBytes = purgeableBytes + externalBytes
|
||||||
let externalCount = UInt64(vmStatistics.external_page_count)
|
let usedBytes = usedWithoutCache > cacheBytes ? usedWithoutCache - cacheBytes : 0
|
||||||
let purgeableCount = UInt64(vmStatistics.purgeable_count)
|
let clampedUsedBytes = min(usedBytes, totalMemoryBytes)
|
||||||
let activeMemory = activeCount * pageSize
|
let freeComputedBytes = totalMemoryBytes > clampedUsedBytes ? totalMemoryBytes - clampedUsedBytes : 0
|
||||||
let inactiveMemory = inactiveCount * pageSize
|
let nonAppBytes = wiredBytes + compressedBytes
|
||||||
let wiredMemory = wiredCount * pageSize
|
let appBytes = clampedUsedBytes > nonAppBytes ? clampedUsedBytes - nonAppBytes : 0
|
||||||
let compressedMemory = compressorCount * pageSize
|
|
||||||
let purgeableMemory = purgeableCount * pageSize
|
|
||||||
let externalMemory = externalCount * pageSize
|
|
||||||
let usedMemory = totalMemory > freeMemory ? totalMemory - freeMemory : 0
|
|
||||||
let appMemory = usedMemory > (wiredMemory + compressedMemory) ? usedMemory - wiredMemory - compressedMemory : 0
|
|
||||||
let cacheMemory = purgeableMemory + externalMemory
|
|
||||||
|
|
||||||
var pressureLevelRaw: Int32 = 0
|
var pressureLevelRaw: Int32 = 0
|
||||||
var pressureSize = MemoryLayout<Int32>.size
|
var pressureSize = MemoryLayout<Int32>.size
|
||||||
|
|
@ -807,17 +822,17 @@ class StatsManager: ObservableObject {
|
||||||
freeBytes: UInt64(swapUsage.xsu_avail)
|
freeBytes: UInt64(swapUsage.xsu_avail)
|
||||||
)
|
)
|
||||||
|
|
||||||
let usage = Double(usedMemory) / Double(totalMemory) * 100.0
|
let usage = Double(clampedUsedBytes) / Double(totalMemoryBytes) * 100.0
|
||||||
let breakdown = MemoryBreakdown(
|
let breakdown = MemoryBreakdown(
|
||||||
totalBytes: totalMemory,
|
totalBytes: totalMemoryBytes,
|
||||||
usedBytes: usedMemory,
|
usedBytes: clampedUsedBytes,
|
||||||
freeBytes: freeMemory,
|
freeBytes: freeComputedBytes,
|
||||||
wiredBytes: wiredMemory,
|
wiredBytes: wiredBytes,
|
||||||
activeBytes: activeMemory,
|
activeBytes: activeBytes,
|
||||||
inactiveBytes: inactiveMemory,
|
inactiveBytes: inactiveBytes,
|
||||||
compressedBytes: compressedMemory,
|
compressedBytes: compressedBytes,
|
||||||
appBytes: appMemory,
|
appBytes: appBytes,
|
||||||
cacheBytes: cacheMemory,
|
cacheBytes: cacheBytes,
|
||||||
swap: swapInfo,
|
swap: swapInfo,
|
||||||
pressure: pressure
|
pressure: pressure
|
||||||
)
|
)
|
||||||
|
|
@ -1237,11 +1252,11 @@ class StatsManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
var networkDownloadString: String {
|
var networkDownloadString: String {
|
||||||
return String(format: "%.1f MB/s", networkDownload)
|
StatsFormatting.throughput(networkDownload)
|
||||||
}
|
}
|
||||||
|
|
||||||
var networkUploadString: String {
|
var networkUploadString: String {
|
||||||
return String(format: "%.1f MB/s", networkUpload)
|
StatsFormatting.throughput(networkUpload)
|
||||||
}
|
}
|
||||||
|
|
||||||
var diskReadString: String {
|
var diskReadString: String {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue