Skip to content

Link: work-ceiling retries without alternatives cost ~6 min on fernflower #92

Open

Description

@bnaudts

Follow-up to #89 (fix 9d4c768). With alternatives on, about a dozen methods per iteration reach the work ceiling in LinkComputerImpl.doMethod and are analysed a second time without alternatives. On fernflower (PARALLEL=1) that comes to:

setting run time ceiling retries
alternatives off 29 min 0
alternatives + both #89 rules 35 min 117
fresh-object rule only 37 min 137

The retries recur every iteration for the same methods: each time they spend the full ceiling and then fall back.

Ideas:

On guava there are no retries (0 in both legs), so this is a fernflower-shaped cost.

Activity

  1. added
    enhancementNew feature or request
    engine:linkThe link engine and shared-variable reconstruction
    on Nov 3, 2026
  2. bnaudts commented on Nov 6, 2026

    @bnaudts
    Author

    Probably the same cause as #97. DomHelper.findGeneralStatement sits at 87% of the work ceiling with 15,302 ∩ facts out of about 16,950 (90%). About half are materialized from dying temporaries, and most of the rest is ∩ copied along aliases. Details and the proposed direction in #97.

  3. bnaudts commented on Nov 9, 2026

    @bnaudts
    Author

    Findings, 2026-11-08/09: computing ∩ on demand (class model)

    Where things stand. The class model is opt-in (IMPLICIT=1). The old derivation is the default again (5b8e32f), because making the class model the default failed 10 tests in the maddi gate.

    Who reads ∩

    • Analyzer, method and parameter independence: never judged. LinkToField deliberately skips ∩.
    • Analyzer, sensitive spots:
      • FieldAnalyzerImpl.computeIndependent: the catch-all for non-decoration links.
      • The one-hop local elimination: field ∩ local becomes field ~ p, a nature that is judged.
      • ShadowModificationPass.followsReturnLink: any link between two real variables carries modification.
      • The guard warning.
    • Link engine:
      • Modification within a method ignores ∩.
      • WriteLinksAndModification: a mutual rv ∩ Y becomes a §m ≡.
      • RedundantLinks: groups ∩ with ≤/≥, so a ∩ can drop a ≤/≥.

    So ∩ moves verdicts mostly by being converted into something else.

    Semantics

    ∩ is absorbing and ∩∘∩ = ∩. The complete fixpoint is therefore a set of classes, and the class model computes exactly that. The old engine's set is incomplete and order-dependent, so any complete algorithm differs from it somewhere.

    ∩ only for summary variables (OVLRELEVANT)

    ∩ was answered only for parameters, the return value, this and fields.

    corpus verdict-diff lines vs old engine, class model the same, summary variables only
    elasticsearch 2 0
    langchain4j 40 16
    fernflower 60 72
    timefold 46 54

    Fernflower's EcjSwitchCandidate fields become @Dependent. GenericType.parse and four ElementAwareLinkedListTest methods become modifying. The analyzer suite loses two expected local ∩s (TestInstanceOf, TestModificationBasics.test3). So ∩ between locals does reach verdicts, and restricting it to the summary is not an option.

    Cost of the class model

    On elasticsearch: 625 s, against 108 s for the old engine. The time goes to full rebuilds of the classes after every closure change, and to the before/after rebuilds of the freeze at every vertex removal.

    Look-ups are cheap: 60–70% are cache hits. The worst method is DesiredBalanceComputer.compute, at 33 s per pass, 12 s of it in ∩.

    Tried, measured and reverted. Both were exact; OVLCHECK found no mismatch and the corpus verdicts were identical:

    • Freeze skips the after-partition when no class can break. Saved ~10% of freeze time, nothing measurable overall.
    • Per-hub creation memo on per-row closure versions. No gain. A hub's creations are linear in its degree, and checking the signature costs as much as recomputing them.

    What precedes each rebuild (langchain4j): 28% follow only new facts, and the classes only grew in all of them. 72% follow a removal or a label change, mostly temporaries leaving the graph.

    Keeping the classes up to date incrementally therefore saves at most ~30–40% of the ∩ bookkeeping. That might bring elasticsearch to about 550 s, still far from 108 s. Not built.

    Open

    • Per-statement snapshot: compute ∩ once per statement instead of per change. This is the only lever that cuts rebuilds by a large factor, but it changes results relative to the class model and would need its own verdict comparison.
    • Root causes of the verdict differences:
      • The ChatRequestOptions.Builder.addListenerAttribute context: the old engine derives key ∩ value, and an isolated probe does not reproduce it.
      • Fernflower ExprProcessor.
      • The ShallowMethodAnalyzer cascade in langchain4j (EmbeddingModel).

    Diagnostic gates left in place

    All are off by default: IMPLICIT, OVLSTATS (timing counters), OVLRELEVANT, OVERLAPSEARCH, NOCHAIN, NOOVERLAP. OVLCHECK went with the reverted shortcuts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    engine:linkThe link engine and shared-variable reconstructionenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions