Skip to content

Commit 190cc85

Browse files
simbasimba
authored andcommitted
feat: add download speed and progress bar UX
1 parent 608a387 commit 190cc85

1 file changed

Lines changed: 58 additions & 4 deletions

File tree

Sources/mlx-server/Server.swift

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,61 @@ import MLXVLM
2121

2222
// ── CLI ──────────────────────────────────────────────────────────────────────
2323

24+
final class ProgressTracker {
25+
var lastUpdate: TimeInterval = 0
26+
var lastBytes: Int64 = 0
27+
var speedStr = "0.0 MB/s"
28+
var isDone = false
29+
30+
func printProgress(_ progress: Progress) {
31+
if isDone { return }
32+
let now = Date().timeIntervalSince1970
33+
34+
let completed = progress.completedUnitCount
35+
let total = progress.totalUnitCount
36+
let fraction = progress.fractionCompleted
37+
38+
if lastUpdate == 0 { lastUpdate = now }
39+
let interval = now - lastUpdate
40+
41+
if interval >= 0.5 {
42+
let diff = Double(completed - lastBytes)
43+
let speedMBps = (diff / interval) / 1_048_576.0
44+
speedStr = String(format: "%.1f MB/s", speedMBps)
45+
46+
lastBytes = completed
47+
lastUpdate = now
48+
}
49+
50+
let pct = Int(fraction * 100)
51+
let completedMB = String(format: "%.1f", Double(completed) / 1_048_576)
52+
let totalMB = String(format: "%.1f", Double(total) / 1_048_576)
53+
54+
let barLength = 20
55+
let completedBars = min(barLength, Int(fraction * Double(barLength)))
56+
let emptyBars = max(0, barLength - completedBars)
57+
58+
var bars = ""
59+
if completedBars > 0 {
60+
bars += String(repeating: "=", count: completedBars - 1) + ">"
61+
} else {
62+
bars += ""
63+
}
64+
bars += String(repeating: " ", count: emptyBars)
65+
66+
let pctStr = String(format: "%3d%%", pct)
67+
let msg = String(format: "\r[mlx-server] Download: [%@] %@ (%@ MB / %@ MB) | Speed: %@", bars, pctStr, completedMB, totalMB, speedStr)
68+
69+
print(msg.padding(toLength: 100, withPad: " ", startingAt: 0), terminator: "")
70+
fflush(stdout)
71+
72+
if fraction >= 1.0 {
73+
print("")
74+
isDone = true
75+
}
76+
}
77+
}
78+
2479
@main
2580
struct MLXServer: AsyncParsableCommand {
2681
static let configuration = CommandConfiguration(
@@ -170,20 +225,19 @@ struct MLXServer: AsyncParsableCommand {
170225

171226
let isVision = self.vision
172227
let container: ModelContainer
228+
let tracker = ProgressTracker()
173229
if isVision {
174230
print("[mlx-server] Loading VLM (vision-language model)...")
175231
container = try await VLMModelFactory.shared.loadContainer(
176232
configuration: modelConfig
177233
) { progress in
178-
let pct = Int(progress.fractionCompleted * 100)
179-
print("[mlx-server] Download: \(pct)%")
234+
tracker.printProgress(progress)
180235
}
181236
} else {
182237
container = try await LLMModelFactory.shared.loadContainer(
183238
configuration: modelConfig
184239
) { progress in
185-
let pct = Int(progress.fractionCompleted * 100)
186-
print("[mlx-server] Download: \(pct)%")
240+
tracker.printProgress(progress)
187241
}
188242
}
189243

0 commit comments

Comments
 (0)