Severity
LOW (redundant work on the export path; scales with history depth)
Summary
Inside the export pagination loop, the code sorts the entire page only to read its single minimum element (to advance the before cursor). The full O(p log p) sort is wasted — a linear min scan suffices.
Location / Evidence
whitenoise-mac/Core/ConversationTranscriptExport.swift:112-120
guard page.hasMoreBefore else { break }
let orderedPage = sortChronologically(page.messages)
guard let oldest = orderedPage.first else { // only .first is used
throw ExportError.emptyPageWithMoreHistory
}
let nextBefore = oldest.timelineAt
let nextBeforeMessageId = oldest.messageIdHex
The only sort that is actually required is the final sortChronologically(Array(collectedById.values)) at :131 (dictionary values are unordered).
Failure scenario
Exporting a 10k-message group with pageLimit = 200 walks ~50 pages, sorting 200 elements each iteration (~50 × 200 log 200 comparisons) purely to find each page's minimum, instead of ~50 × 200 with a linear scan. The cost grows with history depth on the export path.
Why this is not a duplicate
Suggested fix
Replace the per-page sort with a single min scan using the same strict-weak comparator:
guard let oldest = page.messages.min(by: { lhs, rhs in
lhs.timelineAt != rhs.timelineAt ? lhs.timelineAt < rhs.timelineAt
: lhs.messageIdHex < rhs.messageIdHex
}) else { throw ExportError.emptyPageWithMoreHistory }
Keep the single sortChronologically(...) at :131 for output ordering.
Found during a full-codebase review.
Severity
LOW (redundant work on the export path; scales with history depth)
Summary
Inside the export pagination loop, the code sorts the entire page only to read its single minimum element (to advance the
beforecursor). The fullO(p log p)sort is wasted — a linear min scan suffices.Location / Evidence
whitenoise-mac/Core/ConversationTranscriptExport.swift:112-120The only sort that is actually required is the final
sortChronologically(Array(collectedById.values))at:131(dictionary values are unordered).Failure scenario
Exporting a 10k-message group with
pageLimit = 200walks ~50 pages, sorting 200 elements each iteration (~50 × 200 log 200 comparisons) purely to find each page's minimum, instead of ~50 × 200 with a linear scan. The cost grows with history depth on the export path.Why this is not a duplicate
makeDocumentre-sorting the final full history — a different location/call.This per-page sort-to-find-min in the fetch loop is not covered by any of them.
Suggested fix
Replace the per-page sort with a single min scan using the same strict-weak comparator:
Keep the single
sortChronologically(...)at:131for output ordering.Found during a full-codebase review.