mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 02:26:37 +00:00
feat(scarfmon): split nous.readCache into fileExists/readFile/decode/bytes
Last perf capture showed nous.readCache as a single 60-second interval — but the function does three things (transport.fileExists, transport.readFile, JSONDecoder). Splitting the measure points so the next capture localizes which step actually owns the wall-clock. Adds: - nous.readCache.fileExists (interval) — SSH `test -e` round-trip - nous.readCache.readFile (interval) — SSH `cat` round-trip - nous.readCache.bytes (event) — payload size of the cache file - nous.readCache.decode (interval) — JSON parsing cost If the next 60-second beach ball localizes to readFile, we know the cache file is somehow huge or the SSH read is hung; if it's fileExists, the path resolution is the issue; if decode, we have malformed JSON. All three wear the same outer wrapper so the existing nous.readCache total stays for trend comparison. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -98,19 +98,36 @@ public struct NousModelCatalogService: Sendable {
|
|||||||
public func readCache() -> NousModelsCache? {
|
public func readCache() -> NousModelsCache? {
|
||||||
ScarfMon.measure(.diskIO, "nous.readCache") {
|
ScarfMon.measure(.diskIO, "nous.readCache") {
|
||||||
let transport = context.makeTransport()
|
let transport = context.makeTransport()
|
||||||
guard transport.fileExists(cachePath) else { return nil }
|
// Split into separate measure points so the next perf
|
||||||
|
// capture localizes the 60-second observed beach ball
|
||||||
|
// — was it the fileExists probe, the read itself, or
|
||||||
|
// the JSON decode? Each on its own ScarfMon row.
|
||||||
|
let exists = ScarfMon.measure(.diskIO, "nous.readCache.fileExists") {
|
||||||
|
transport.fileExists(cachePath)
|
||||||
|
}
|
||||||
|
guard exists else { return nil }
|
||||||
do {
|
do {
|
||||||
let data = try transport.readFile(cachePath)
|
let data = try ScarfMon.measure(.diskIO, "nous.readCache.readFile") {
|
||||||
|
try transport.readFile(cachePath)
|
||||||
|
}
|
||||||
|
ScarfMon.event(.diskIO, "nous.readCache.bytes", count: 1, bytes: data.count)
|
||||||
|
return ScarfMon.measure(.diskIO, "nous.readCache.decode") {
|
||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
decoder.dateDecodingStrategy = .iso8601
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
do {
|
||||||
let cache = try decoder.decode(NousModelsCache.self, from: data)
|
let cache = try decoder.decode(NousModelsCache.self, from: data)
|
||||||
guard cache.version == NousModelsCache.currentVersion else {
|
guard cache.version == NousModelsCache.currentVersion else {
|
||||||
Self.logger.info("nous models cache schema mismatch (got v\(cache.version), expected v\(NousModelsCache.currentVersion)); ignoring")
|
Self.logger.info("nous models cache schema mismatch (got v\(cache.version), expected v\(NousModelsCache.currentVersion)); ignoring")
|
||||||
return nil
|
return Optional<NousModelsCache>.none
|
||||||
}
|
}
|
||||||
return cache
|
return cache
|
||||||
} catch {
|
} catch {
|
||||||
Self.logger.warning("couldn't decode nous models cache: \(error.localizedDescription, privacy: .public)")
|
Self.logger.warning("couldn't decode nous models cache: \(error.localizedDescription, privacy: .public)")
|
||||||
|
return Optional<NousModelsCache>.none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Self.logger.warning("couldn't read nous models cache: \(error.localizedDescription, privacy: .public)")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user