Skip to content

Safe-delete reference scans do one blocking round trip per method environment, so the editor freeze scales with maxEnvironment #483

Description

@ericwinger

Summary

Every guarded delete in the GemStone Explorer scans the image for what still references the
target. That scan is run once per method environment, one after another, and each one blocks
the extension host
. On a stone with gemstone.maxEnvironment above 0 the editor therefore
freezes for N whole-image scans instead of one, and the freeze gets linearly longer with every
environment configured. A progress notification is shown, but it cannot spin — the GCI calls are
synchronous — so what the user sees is a frozen window for N times as long as it needs to be.

This is a performance problem, not a correctness one: the results are right, they just cost far
more than they should. Raised in review of #476 and agreed there as follow-up work rather than
something to hold that PR for.

Where

ExplorerController.scanReferences in client/src/gemstoneExplorer.ts:

const perEnv = this.environmentsToScan().map((env) => scan(env));

environmentsToScan() answers 0..gemstone.maxEnvironment, and scan is one blocking GCI round
trip. All four guarded deletes go through it — remove method, remove class, remove instance
variable, remove class variable — via sendersOf, referencesToClassInDict,
methodsAccessingInstVar and methodsAccessingClassVar in client/src/queries/.

What to do instead

Push the environment loop into the Smalltalk side so one round trip answers for every
environment, with the environment carried on each returned row. The row format already has a
column for it (methodSerialization in client/src/queries/methodSearch.ts emits it, and
MethodSearchResult.environmentId consumes it), so this is a change to how the scan is driven
rather than to what a result looks like.

Points to keep:

  • The client already folds rows from several environments into one list with
    dedupeMethodResults, which treats class, side, selector and environment as a method's
    identity. A server-side loop must keep producing rows that fold the same way.
  • The row cap is applied per query today, and scanReferences reports the scan as truncated
    when any single environment comes back full. Whatever replaces it has to keep answering the
    same question — "were rows dropped?" — because the confirmation states its count as a floor
    rather than as fact when they were.
  • The same one-query-per-environment shape exists in the Senders / Implementors / hierarchy
    implementors / References commands in client/src/extension.ts, which sweep
    0..maxEnvironment in a for loop. Worth fixing together, since a shared scan primitive is
    the natural home for it — see the companion cleanup issue.

Acceptance criteria

  • A guarded delete costs one round trip regardless of gemstone.maxEnvironment.
  • Freeze time no longer scales with the number of environments configured.
  • Results are unchanged: the same methods are found, still carrying the environment they were
    found in, and the truncation hedge still appears when rows were dropped.
  • The single-environment case (maxEnvironment at its default of 0) is no slower than today.

Reference

Review comment: #476 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestexplorerFeatures/fixes related to GemStone explorerideIDE component

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions