Skip to content

findEntryPoint can take 60+ seconds on large staging dirs (telnet launch hang) #341

@chrisdp

Description

@chrisdp

Symptom

Launching a project in telnet mode (enableDebugProtocol: false) against a large project staging directory hangs in prepareMainProject for ~80 seconds with no visible progress. The launch eventually proceeds but is unusable in practice. Debug-protocol mode only hits this when stopOnEntry: true, so it's gone unnoticed.

Root cause

fileUtils.findEntryPoint (src/FileUtils.ts:261) runs six sequential findInFiles.find calls, each doing a full recursive walk of every .brs file in the staging dir:

let results = {
    ...await findInFiles.find({ term: 'sub\\s+RunScreenSaver\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/),
    ...await findInFiles.find({ term: 'function\\s+RunScreenSaver\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/),
    ...await findInFiles.find({ term: 'sub\\s+RunUserInterface\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/),
    ...await findInFiles.find({ term: 'function\\s+RunUserInterface\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/),
    ...await findInFiles.find({ term: 'sub\\s+main\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/),
    ...await findInFiles.find({ term: 'function\\s+main\\s*\\(', flags: 'ig' }, projectPath, /.*\.brs/)
};

Each call is serial. The early calls keep running even after a match has been found, and the searches all walk the same tree six times.

Measured timing

On a large staging directory, with main at source/main.brs:1:

22:01:45.641  findEntryPoint() in /Users/.../out/.roku-deploy-staging
22:03:09.835  findEntryPoint() resolved (entryPath: source/main.brs, lineNumber: 1)

~84 seconds for a function that resolves at the first file checked.

Fix options

  1. Parallel + early-exitPromise.all the six calls; short-circuit when any returns a match. ~6x speedup worst case, near-instant when main is at the root.
  2. Single combined regex – one findInFiles.find with (?:sub|function)\s+(?:RunScreenSaver|RunUserInterface|main)\s*\(. One tree walk.
  3. Use brighterscript – there's already a BscProjectThreaded activated against the staging dir; ask it for the entry function symbol instead of grepping files. Probably overkill.

(2) is the smallest, most direct fix. (1) is the safest mechanical change.

Repro

  • Telnet launch (enableDebugProtocol: false)
  • Project with deepLinkUrl set (so registerEntryBreakpoint actually runs in telnet mode), OR stopOnEntry: true
  • Staging directory with many .brs files

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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