Skip to content

Performance: ConversationTranscriptExport.fetchAllMessages full-sorts every page just to pick the pagination anchor (redundant O(p log p) per page) #587

Description

@erskingardner

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    LOWSeverity: LOWagent-okbugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions