feat: moved from binary to metric based size units to have the same calculation as macOS (#2230)

This commit is contained in:
Serhiy Mytrovtsiy
2024-12-17 14:13:58 +01:00
parent 8a99997f86
commit 3887157a7c
4 changed files with 50 additions and 35 deletions

View File

@@ -132,16 +132,16 @@ public struct Units {
} }
public var kilobytes: Double { public var kilobytes: Double {
return Double(bytes) / 1_024 return Double(bytes) / 1_000
} }
public var megabytes: Double { public var megabytes: Double {
return kilobytes / 1_024 return kilobytes / 1_000
} }
public var gigabytes: Double { public var gigabytes: Double {
return megabytes / 1_024 return megabytes / 1_000
} }
public var terabytes: Double { public var terabytes: Double {
return gigabytes / 1_024 return gigabytes / 1_000
} }
public func getReadableTuple(base: DataSizeBase = .byte) -> (String, String) { public func getReadableTuple(base: DataSizeBase = .byte) -> (String, String) {
@@ -149,15 +149,15 @@ public struct Units {
let multiplier: Double = base == .byte ? 1 : 8 let multiplier: Double = base == .byte ? 1 : 8
switch bytes { switch bytes {
case 0..<1_024: case 0..<1_000:
return ("0", "K\(stringBase)/s") return ("0", "K\(stringBase)/s")
case 1_024..<(1_024 * 1_024): case 1_000..<(1_000 * 1_000):
return (String(format: "%.0f", kilobytes*multiplier), "K\(stringBase)/s") return (String(format: "%.0f", kilobytes*multiplier), "K\(stringBase)/s")
case 1_024..<(1_024 * 1_024 * 100): case 1_000..<(1_000 * 1_000 * 100):
return (String(format: "%.1f", megabytes*multiplier), "M\(stringBase)/s") return (String(format: "%.1f", megabytes*multiplier), "M\(stringBase)/s")
case (1_024 * 1_024 * 100)..<(1_024 * 1_024 * 1_024): case (1_000 * 1_000 * 100)..<(1_000 * 1_000 * 1_000):
return (String(format: "%.0f", megabytes*multiplier), "M\(stringBase)/s") return (String(format: "%.0f", megabytes*multiplier), "M\(stringBase)/s")
case (1_024 * 1_024 * 1_024)...Int64.max: case (1_000 * 1_000 * 1_000)...Int64.max:
return (String(format: "%.1f", gigabytes*multiplier), "G\(stringBase)/s") return (String(format: "%.1f", gigabytes*multiplier), "G\(stringBase)/s")
default: default:
return (String(format: "%.0f", kilobytes*multiplier), "K\(stringBase)B/s") return (String(format: "%.0f", kilobytes*multiplier), "K\(stringBase)B/s")
@@ -169,19 +169,19 @@ public struct Units {
let multiplier: Double = base == .byte ? 1 : 8 let multiplier: Double = base == .byte ? 1 : 8
switch bytes*Int64(multiplier) { switch bytes*Int64(multiplier) {
case 0..<1_024: case 0..<1_000:
let unit = omitUnits ? "" : " K\(stringBase)/s" let unit = omitUnits ? "" : " K\(stringBase)/s"
return "0\(unit)" return "0\(unit)"
case 1_024..<(1_024 * 1_024): case 1_000..<(1_000 * 1_000):
let unit = omitUnits ? "" : " K\(stringBase)/s" let unit = omitUnits ? "" : " K\(stringBase)/s"
return String(format: "%.0f\(unit)", kilobytes*multiplier) return String(format: "%.0f\(unit)", kilobytes*multiplier)
case 1_024..<(1_024 * 1_024 * 100): case 1_000..<(1_000 * 1_000 * 100):
let unit = omitUnits ? "" : " M\(stringBase)/s" let unit = omitUnits ? "" : " M\(stringBase)/s"
return String(format: "%.1f\(unit)", megabytes*multiplier) return String(format: "%.1f\(unit)", megabytes*multiplier)
case (1_024 * 1_024 * 100)..<(1_024 * 1_024 * 1_024): case (1_000 * 1_000 * 100)..<(1_000 * 1_000 * 1_000):
let unit = omitUnits ? "" : " M\(stringBase)/s" let unit = omitUnits ? "" : " M\(stringBase)/s"
return String(format: "%.0f\(unit)", megabytes*multiplier) return String(format: "%.0f\(unit)", megabytes*multiplier)
case (1_024 * 1_024 * 1_024)...Int64.max: case (1_000 * 1_000 * 1_000)...Int64.max:
let unit = omitUnits ? "" : " G\(stringBase)/s" let unit = omitUnits ? "" : " G\(stringBase)/s"
return String(format: "%.1f\(unit)", gigabytes*multiplier) return String(format: "%.1f\(unit)", gigabytes*multiplier)
default: default:
@@ -190,17 +190,17 @@ public struct Units {
} }
} }
public func getReadableMemory() -> String { public func getReadableMemory(to round: Int = 1) -> String {
switch bytes { switch bytes {
case 0..<1_024: case 0..<1_000:
return "0 KB" return "0 KB"
case 1_024..<(1_024 * 1_024): case 1_000..<(1_000 * 1_000):
return String(format: "%.0f KB", kilobytes) return String(format: "%.0f KB", kilobytes)
case 1_024..<(1_024 * 1_024 * 1_024): case 1_000..<(1_000 * 1_000 * 1_000):
return String(format: "%.0f MB", megabytes) return String(format: "%.0f MB", megabytes)
case 1_024..<(1_024 * 1_024 * 1_024 * 1_024): case 1_000..<(1_000 * 1_000 * 1_000 * 1_000):
return String(format: "%.1f GB", gigabytes) return String(format: "%.1f GB", gigabytes)
case (1_024 * 1_024 * 1_024 * 1_024)...Int64.max: case (1_000 * 1_000 * 1_000 * 1_000)...Int64.max:
return String(format: "%.1f TB", terabytes) return String(format: "%.1f TB", terabytes)
default: default:
return String(format: "%.0f KB", kilobytes) return String(format: "%.0f KB", kilobytes)

View File

@@ -382,13 +382,13 @@ extension SizeUnit: CaseIterable {
public func toBytes(_ value: Int) -> Int { public func toBytes(_ value: Int) -> Int {
switch self { switch self {
case .KB: case .KB:
return value * 1_024 return value * 1_000
case .MB: case .MB:
return value * 1_024 * 1_024 return value * 1_000 * 1_000
case .GB: case .GB:
return value * 1_024 * 1_024 * 1_024 return value * 1_000 * 1_000 * 1_000
case .TB: case .TB:
return value * 1_024 * 1_024 * 1_024 * 1_024 return value * 1_000 * 1_000 * 1_000 * 1_000
default: default:
return value return value
} }

View File

@@ -193,6 +193,9 @@ public class ProcessReader: Reader<[TopProcess]> {
usage *= 1024 // apply gigabyte multiplier usage *= 1024 // apply gigabyte multiplier
} else if usageString.last == "K" { } else if usageString.last == "K" {
usage /= 1024 // apply kilobyte divider usage /= 1024 // apply kilobyte divider
} else if usageString.last == "M" && usageString.count == 5 {
usage /= 1024
usage *= 1000
} }
var name: String = command var name: String = command
@@ -200,6 +203,6 @@ public class ProcessReader: Reader<[TopProcess]> {
name = n name = n
} }
return TopProcess(pid: pid, name: name, usage: usage * Double(1024 * 1024)) return TopProcess(pid: pid, name: name, usage: usage * Double(1000 * 1000))
} }
} }

View File

@@ -17,53 +17,65 @@ class RAM: XCTestCase {
var process = ProcessReader.parseProcess("3127 lldb-rpc-server 611M") var process = ProcessReader.parseProcess("3127 lldb-rpc-server 611M")
XCTAssertEqual(process.pid, 3127) XCTAssertEqual(process.pid, 3127)
XCTAssertEqual(process.name, "lldb-rpc-server") XCTAssertEqual(process.name, "lldb-rpc-server")
XCTAssertEqual(process.usage, 611 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 611 * Double(1000 * 1000))
process = ProcessReader.parseProcess("257 WindowServer 210M") process = ProcessReader.parseProcess("257 WindowServer 210M")
XCTAssertEqual(process.pid, 257) XCTAssertEqual(process.pid, 257)
XCTAssertEqual(process.name, "WindowServer") XCTAssertEqual(process.name, "WindowServer")
XCTAssertEqual(process.usage, 210 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 210 * Double(1000 * 1000))
process = ProcessReader.parseProcess("7752 phpstorm 1819M") process = ProcessReader.parseProcess("7752 phpstorm 1819M")
XCTAssertEqual(process.pid, 7752) XCTAssertEqual(process.pid, 7752)
XCTAssertEqual(process.name, "phpstorm") XCTAssertEqual(process.name, "phpstorm")
XCTAssertEqual(process.usage, 1819 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 1819.0 / 1024 * 1000 * Double(1000 * 1000))
process = ProcessReader.parseProcess("359 NotificationCent 62M") process = ProcessReader.parseProcess("359 NotificationCent 62M")
XCTAssertEqual(process.pid, 359) XCTAssertEqual(process.pid, 359)
XCTAssertEqual(process.name, "NotificationCent") XCTAssertEqual(process.name, "NotificationCent")
XCTAssertEqual(process.usage, 62 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 62 * Double(1000 * 1000))
process = ProcessReader.parseProcess("623 SafariCloudHisto 1608K") process = ProcessReader.parseProcess("623 SafariCloudHisto 1608K")
XCTAssertEqual(process.pid, 623) XCTAssertEqual(process.pid, 623)
XCTAssertEqual(process.name, "SafariCloudHisto") XCTAssertEqual(process.name, "SafariCloudHisto")
XCTAssertEqual(process.usage, (1608/1024) * Double(1024 * 1024)) XCTAssertEqual(process.usage, (1608/1024) * Double(1000 * 1000))
process = ProcessReader.parseProcess("174 WindowServer 1442M+ ") process = ProcessReader.parseProcess("174 WindowServer 1442M+ ")
XCTAssertEqual(process.pid, 174) XCTAssertEqual(process.pid, 174)
XCTAssertEqual(process.name, "WindowServer") XCTAssertEqual(process.name, "WindowServer")
XCTAssertEqual(process.usage, 1442 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 1442 * Double(1000 * 1000))
process = ProcessReader.parseProcess("329 Finder 488M+ ") process = ProcessReader.parseProcess("329 Finder 488M+ ")
XCTAssertEqual(process.pid, 329) XCTAssertEqual(process.pid, 329)
XCTAssertEqual(process.name, "Finder") XCTAssertEqual(process.name, "Finder")
XCTAssertEqual(process.usage, 488 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 488 * Double(1000 * 1000))
process = ProcessReader.parseProcess("7163* AutoCAD LT 2023 11G ") process = ProcessReader.parseProcess("7163* AutoCAD LT 2023 11G ")
XCTAssertEqual(process.pid, 7163) XCTAssertEqual(process.pid, 7163)
XCTAssertEqual(process.name, "AutoCAD LT 2023") XCTAssertEqual(process.name, "AutoCAD LT 2023")
XCTAssertEqual(process.usage, 11 * Double(1024 * 1024 * 1024)) XCTAssertEqual(process.usage, 11 * Double(1024 * 1000 * 1000))
} }
func testKernelTask() throws { func testKernelTask() throws {
var process = ProcessReader.parseProcess("0 kernel_task 270M ") var process = ProcessReader.parseProcess("0 kernel_task 270M ")
XCTAssertEqual(process.pid, 0) XCTAssertEqual(process.pid, 0)
XCTAssertEqual(process.name, "kernel_task") XCTAssertEqual(process.name, "kernel_task")
XCTAssertEqual(process.usage, 270 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 270 * Double(1000 * 1000))
process = ProcessReader.parseProcess("0 kernel_task 280M") process = ProcessReader.parseProcess("0 kernel_task 280M")
XCTAssertEqual(process.pid, 0) XCTAssertEqual(process.pid, 0)
XCTAssertEqual(process.name, "kernel_task") XCTAssertEqual(process.name, "kernel_task")
XCTAssertEqual(process.usage, 280 * Double(1024 * 1024)) XCTAssertEqual(process.usage, 280 * Double(1000 * 1000))
}
func testSizes() throws {
var process = ProcessReader.parseProcess("0 com.apple.Virtua 8463M")
XCTAssertEqual(process.pid, 0)
XCTAssertEqual(process.name, "com.apple.Virtua")
XCTAssertEqual(process.usage, 8463.0 / 1024 * 1000 * 1000 * 1000)
process = ProcessReader.parseProcess("0 Safari 658M")
XCTAssertEqual(process.pid, 0)
XCTAssertEqual(process.name, "Safari")
XCTAssertEqual(process.usage, 658 * Double(1000 * 1000))
} }
} }