// Author: Simon-Pierre Boucher — contact@spboucher.ai // // Chip name, core count and unified memory via sysctl — feeds the memory // estimate badge in the New Run form. import Foundation enum SystemInfo { static func sysctlString(_ name: String) -> String? { var size = 0 guard sysctlbyname(name, nil, &size, nil, 0) == 0, size > 0 else { return nil } var buf = [CChar](repeating: 0, count: size) guard sysctlbyname(name, &buf, &size, nil, 0) == 0 else { return nil } return String(cString: buf) } static func sysctlInt(_ name: String) -> Int64? { var value: Int64 = 0 var size = MemoryLayout.size guard sysctlbyname(name, &value, &size, nil, 0) == 0 else { return nil } return value } static var chipName: String { sysctlString("machdep.cpu.brand_string") ?? "Apple Silicon" } static var memoryBytes: Int64 { sysctlInt("hw.memsize") ?? 0 } static var cpuCores: Int { Int(sysctlInt("hw.ncpu") ?? 0) } /// Rough training footprint: weights+grads+AdamW moments in f32 (4 copies /// of params × 4 bytes) + activation estimate per micro-batch. static func estimatedTrainingBytes(config: ForgeConfig) -> Int64 { let params = Int64(config.model.paramCount) let states = params * 4 * 4 let actPerToken = Int64(config.model.nLayers * config.model.dModel * 24) let activations = actPerToken * Int64(config.train.batchSize * config.model.contextLength) return states + activations } }