Skip to content

perf: helpers reading several fields of one or two parameters pay a full IC tower per read and boxed arithmetic (cli-table3 layout: 13x Node instructions) #12328

Closed

Description

@proggeramlug

A helper that reads several fields from one or two untyped parameters pays a full inline-cache tower per read: a receiver check, a shape compare and a boxed result. Arithmetic on those values is guarded and generic. Real example: cli-table3's layout code. A verbatim copy of its nine layout functions, laying out a 2,000 × 7 table, costs 69.4 G instructions on Perry vs 5.3 G on Node, with 6.5 s vs 0.6 s wall (main 718ca28).

function cellsConflict(cell1, cell2) {
  let yMin1 = cell1.y;
  let yMax1 = cell1.y - 1 + (cell1.rowSpan || 1);
  let yMin2 = cell2.y;
  let yMax2 = cell2.y - 1 + (cell2.rowSpan || 1);
  let yConflict = !(yMin1 > yMax2 || yMin2 > yMax1);
  let xMin1 = cell1.x;
  let xMax1 = cell1.x - 1 + (cell1.colSpan || 1);
  let xMin2 = cell2.x;
  let xMax2 = cell2.x - 1 + (cell2.colSpan || 1);
  let xConflict = !(xMin1 > xMax2 || xMin2 > xMax1);
  return yConflict && xConflict;
}

What happens

cellsConflict takes 52% of self cycles and its caller conflictExists 35%; the generic IC front takes 7–11%.

  • One IC site per read. The 12 reads are independent generic sites (expr/property_get/generic_dispatch.rs). The existing statement-run read regions (expr/region_read_run.rs, stmt/region_read_stmts.rs) need consecutive let a = o.k statements, so operator trees that mix two receivers with || never form a run.
  • No field representation. A hit returns a boxed value, because the site word holds (ShapeId, slot) and no field representation. So - 1 + (...), || and > take the guarded_arith / js_is_truthy / dyncmp paths, and each let gets a shadow-root slot.

Proposed direction

Extend the existing read regions, without adding a new mechanism:

Watch the documented regression when a refinable let loses its type (region_read_stmts.rs:84-100).

Related

Witness: the cli-table3 layout micro (layout-micro.ts in lane perry-wgperf), and walletguide's transactions list --limit 2000 --table (8.1 s vs Node's 1.09 s). Details are in secret-tests scratchpad/shape-audit/AUDIT.md, section 2(a) and step 3.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions