renderCost

fun SurfaceModel.renderCost(resolver: ChildResolver, limits: RenderLimits = RenderLimits.DEFAULT, from: ComponentId = Surface.ROOT_ID): RenderCost

What drawing this surface from from would cost, without drawing any of it.

The estimate a renderer consults before it descends. It counts what a composition would create rather than what the agent sent: a reference to a component that has not arrived is a placeholder the renderer composes, so it is charged, and so are the ones a cycle or the depth bound stops -- a surface that is nothing but a million dangling references costs a million placeholders, which is exactly the payload a count of present components would wave through.

Templates are counted at RenderLimits.templateFanout rather than expanded against the data model, which is what makes this an estimate. It is deliberate on both sides: the answer then depends only on the surface's components, so it survives every data model write and can be cached across them, and the count a template really has is bounded when the template is expanded, where the array is in hand.

A surface holding no template is the case where none of that applies, and RenderCost.Fits.exact says so: every other reference names a fixed number of children, so the paths counted here are the instances that will be composed. A renderer that has been told the whole subtree fits has nothing left to ration, and a budget divided down it could then only take children away from a surface that was never going to exceed anything.

Shares walk's traversal, so the child order, the cycle rule, the depth rule and the resolver handling here are not a second implementation of them.